X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.runtime%2Fscl%2FPrelude.scl;h=907d6e00d74084dfc12dddedd205448624ecc2a8;hb=82a87b8535628d47d9c381e1a3a2296fb67c7fd0;hp=c81f8308954e8ee241653b686b8d0bcbeffdaa6c;hpb=c26409b1caf2f1e560d37c5befd11b442399c3fe;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.runtime/scl/Prelude.scl b/bundles/org.simantics.scl.runtime/scl/Prelude.scl index c81f83089..907d6e00d 100644 --- a/bundles/org.simantics.scl.runtime/scl/Prelude.scl +++ b/bundles/org.simantics.scl.runtime/scl/Prelude.scl @@ -74,7 +74,7 @@ infixl 5 (\\), (<<), (<+) infix 4 (!=), (<), (<=), (>=), (>) infixr 3 (&&), (&<&) infixr 2 (||), orElse, morelse -infixr 1 (>>=), (>>), (:=) +infixr 1 (>>=), (>>), (:=), (>=>) infixr 1 ($) infixl 1 catch @@ -123,6 +123,7 @@ uncurry3 f (x, y, z) = f x y z flip :: (a -> b -> c) -> b -> a -> c flip f x y = f y x +"Swaps the order of elements of a pair (2-tuple)." swap :: (a,b) -> (b,a) swap (x,y) = (y,x) @@ -920,6 +921,10 @@ Sequentially compose two actions, discarding any value produced by the first, li (>>) :: Monad m => m a -> m b -> m b a >> b = a >>= (\_ -> b) +"Left-to-right Kleisli composition of monads." +(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c) +(f >=> g) x = (f x) >>= g + "While loop. `while cond body` executes the `body` while the `cond` is true." @inline while :: ( Boolean) -> ( a) -> () @@ -1065,6 +1070,15 @@ mapEither f list = runProc do Right v -> addArrayList r v) (Java.unsafeCoerce l, Java.unsafeCoerce r) +"`replicate n v` returns a list of length `n` such that each element is a copy of `v`." +@inline +replicate :: Integer -> a -> [a] +replicate n v = build (\empty cons -> + let aux 0 l = l + aux i l = aux (i-1) (cons l v) + in aux n empty + ) + /// FunctorM /// class (Functor f) => FunctorM f where @@ -1074,6 +1088,22 @@ class (Functor f) => FunctorM f where sequence :: Monad m => f (m a) -> m (f a) mapM f l = sequence (fmap f l) +/// MonadE /// + +class (FunctorE m, Monad m) => MonadE m where + bindE :: m a -> (a -> m b) -> m b + +instance MonadE Maybe where + bindE Nothing _ = Nothing + bindE (Just v) f = f v + +instance MonadE (Either a) where + bindE (Left v) _ = Left v + bindE (Right v) f = f v + +instance MonadE [] where + bindE l f = concatMap f l + /// Category /// "Identity function." @@ -1273,7 +1303,14 @@ The Either type represents values with two possibilities: a value of type `Eithe The `Either` type is sometimes used to represent a value which is either correct or an error; by convention, the `Left` constructor is used to hold an error value and the `Right` constructor is used to hold a correct value (mnemonic: "right" also means "correct"). """ -data Either a b = Left a | Right b +@JavaType "org.simantics.scl.runtime.either.Either" +data Either a b = + @JavaType "org.simantics.scl.runtime.either.Left" + @FieldNames [value] + Left a + | @JavaType "org.simantics.scl.runtime.either.Right" + @FieldNames [value] + Right b deriving instance (Ord a, Ord b) => Ord (Either a b) deriving instance (Show a, Show b) => Show (Either a b) @@ -1401,6 +1438,17 @@ instance Read String where splitString :: String -> String -> [String] splitString source pattern = arrayToList $ splitString_ source pattern +""" +`split pattern text` splits `text` around matches of the given regular expression `pattern`. + +This function works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array. + +The string "boo:and:foo", for example, yields the following results with these expressions: + + Regex Result + : { "boo", "and", "foo" } + o { "b", "", ":and:f" } +""" split :: String -> String -> [String] split pattern text = arrayToList $ splitString_ text pattern @@ -1535,11 +1583,42 @@ printWithSeparator sb sep l = loop 0 (if i==0 then sb else sb << sep) <+ l!i loop (i+1) -"Joins the string representations of the list of values with the given separator." +""" +Joins the string representations of the list of values with the given separator. + +See [intercalate](#intercalate) for an alternative that works with Strings +and doesn't escape its arguments. +""" joinWithSeparator :: Show a => String -> [a] -> String joinWithSeparator separator values = runProc ( StringBuilder.toString $ printWithSeparator StringBuilder.new separator values) + +""" +The intercalate function takes a String and a list of Strings +and concatenates the list after interspersing the first argument +between each element of the list. + +See also more generic [joinWithSeparator](#joinWithSeparator) +which escapes its arguments using `show`. +""" +intercalate :: String -> [String] -> String +intercalate separator strings = do + l = length strings + if l == 0 + then "" + else if l == 1 + then strings!0 + else runProc do + sb = StringBuilder.new + sb << strings!0 + loop i | i == l = () + | otherwise = do + sb << separator << strings!i + loop (i+1) + loop 1 + StringBuilder.toString sb + instance (Show a) => Show [a] where sb <+ l = do len = length l @@ -2098,7 +2177,7 @@ importJava "org.simantics.scl.runtime.procedure.Procedures" where "Executes the given expression and catches certain class of exceptions (specified by the catch handler that is given as a second parameter.)" @JavaName catch_ - catch :: VecComp ex => ( a) -> (ex -> a) -> a + catch :: VecComp ex => ( a) -> (ex -> a) -> a importJava "java.lang.Throwable" where data Throwable