Compiled: Wed Dec 05 00:00:02 PST 2012 from source file: frege/prelude/PreludeMonad.fr
This package provides the Monad class and related classes and functions.
The class hierarchy is derived from the (Haskell) proposal /The Other Prelude/ but the traditional method names have been kept, except for Applicative.pure which is replaced by Applicative.return. This is because pure cannot be a function name in Frege due to being a keyword.
The functions in this library use the following naming conventions:
filter :: (a -> Bool) - > [a] -> [a] filterM :: (Monad m) => (a -> m Bool) -> [a] -> m [a]
sequence :: Monad m => [m a] -> m [a] sequence_ :: Monad m => [m a] -> m ()
sum :: Num a => [a] -> a msum :: MonadPlus m => [m a] -> m a
This package is /implementation specific/ insofar as the compiler may assume that certain items are defined here in a certain way. Changes may thus lead to compiler crashes or java code that will be rejected by the java compiler.
In particular, desugared do expressions will reference Monad, Monad.>>= and Monad.>>.
This package is implicitly imported and besides the additional stuff covers most of what one would get by importing Control.Monad in Hasekll.
A functor with application, providing operations to
A minimal complete definition must include implementations of these functions satisfying the following laws:
The other methods have the following default definitions, which may be overridden with equivalent specialized implementations:
u *> v = return (const id) <*> u <*> v u <* v = return const <*> u <*> v
As a consequence of these laws, the Functor instance for f will satisfy
fmap f x = return f <*> x
If f is also a Monad, it should satisfy (<*>) = ap (which implies that Applicative.return and Applicative.<*> satisfy the applicative functor laws).
Minimal complete definition: Applicative.return and Applicative.<*>.
Sequence actions, discarding the value of the first argument.
Sequence actions, discarding the value of the second argument.
Sequential application.
Lift a value
For a data type declared like
data D s = native Javatype
where Javatype implements the java.lang.Cloneable interface, one can get implementations for Freezable.freeze and Freezable.thaw by just stating
instance Cloneable D
The Freezable.freeze and Freezable.thaw operations are implemented in terms of Cloneable.clone.
clone v must be a native method that works like java.lang.Object#clone.
Type class for native values that may be used in a functional way. The Freezable.freeze operation is a ST action, but yields a result that can be returned from a ST thread.
To be implemented with care.
"Freeze" a mutable native value. The result is supposed to be immutable or at least not reachable from other parts of the code, especially from java code.
The most prominent way to freeze a value is by Cloneable.clone-ing it, if that is supported.
This is intended for cases where we want to keep the native value and we know that there are no references to the native value other than the ones maintained in the current ST action. In those not so rare cases, it would be overkill to obtain a copy of a value by cloning it or serializing/deserializing it. Hence, an implementation of Freezable.our is allowed to cheat a bit and return just this.
The safety of Freezable operations is something the compiler cannot infer. It lies entirely in the responsibility of the programmer to ensure safety. Remember that violation of the informal contract of Freezable (see below) will be rewarded with exceptions thrown at runtime or with inexplicable, perhaps nondeterministic behaviour of the program.
An example where Freezable.our is employed is creation and initialization of arrays, as in IntArray.fromList. When the array is completely initialized, it is safe to let it escape as a read only value because no further write accesses are possible (unless one manages to pass the array to an impure function.)
This is the informal contract of Freezable and its operations. It is designed so that the type system will detect unsafe usage of mutable native values. The programmer should understand that such type errors are a strong signal to go back and rethink the code. Inventing "clever" workarounds in the form of creatively typed native functions or so is like loading a shotgun that points to ones foot.
The default implementation does the same as Freezable.freeze. A generic native method to implement a low cost Freezable.our is provided in the runtime as frege.RT.our. It just returns its argument.
The inverse of Freezable.freeze creates a value (an object) which can be passed to impure functions without compromising the frozen object passed as argument.
One possibility to thaw an object properly is by cloning it.
If Freezable.thaw is not implemented correctly, bad things may happen.
This function is needed to synchronize pure computations on a native value with manipulations of that same value inside ST actions. Consider the following code:
do arr <- IntArray.new 100 arr.[42 <- 1] let result = arr.elemAt 42 // actually a type error arr.[42 <- 2] return result
The placement of the let does not guarantee that result will be evaluated between the assignments to cell 42 of the array. To the contrary, the read access to the array will most probably not occur before the result of the state action is evaluated. Therefore, such constructs are forbidden through the type of IntArray.elemAt which requires a frozen array.
The let must be replaced by
result <- withFrozen arr (flip IntArray.elemAt 42)
to sequence evaluation before the next write access to the array.
Because Freezable.withFrozen employs Freezable.our it can be as easily misused. In fact withFrozen v id is identical to our v.
The Functor class is used for types that can be mapped over. Instances of Functor should satisfy the following laws:
fmap id == id fmap (f . g) == fmap f . fmap g
ST, State, Either, (,,), (,), []
Map a function over a Functor
The Monad class defines the basic operations over a monad, a concept from a branch of mathematics known as /category theory/. From the perspective of a Frege programmer, however, it is best to think of a monad as an /abstract datatype/ of actions.
Frege’s do expressions provide a convenient syntax for writing monadic expressions.
Minimal complete definition: Monad.>>= and Applicative.return.
Instances of Monad should satisfy the following laws:
return a >>= k == k a m >>= return == m m >>= (\x -> k x >>= h) == (m >>= k) >>= h
Since instances of Monad are also instances of Functor, they additionally shall satisfy the law:
fmap f xs == xs >>= return • f
which is also the default implementation of Functor.fmap.
The instances of Monad for lists, Maybe and ST defined in the Prelude satisfy these laws.
Sequentially compose two actions, discarding any value produced by the first, this works like sequencing operators (such as the semicolon) in imperative languages.
Sequentially compose two actions, passing any value produced by the first as an argument to the second.
The Monad.join function is the conventional monad join operator. It is used to remove one level of monadic structure, projecting its bound argument into the outer level.
The MonadFail class augments Monad by adding the MonadFail.fail operation. This operation is not part of the mathematical definition of a monad.
Fail with a message.
A Monad that also supports choice and failure and observes the following laws:
mzero `mplus` v = v v `mplus` mzero = v (a `mplus` b) `mplus` c = a `mplus` (b `mplus` c) (a `mplus` b) >>= f = (a >>= f) `mplus` (b >>= f)
an associative operation
A Monad with a left identity.
This value should satisfy /left zero/:
mzero >>= f = mzero
For a data type declared like
data D s = native Javatype
where Javatype implements the java.io.Serializable interface, one can get implementations for Freezable.freeze and Freezable.thaw by just stating
instance Serializable D
The Freezable.freeze and Freezable.thaw operations are implemented in terms of copySerializable, which serializes its argument to a byte array and creates a new copy by deserializing it from the byte array.
copySerializable v is supposed to be a native function that is implemented by frege.RT.copySerializable at the instantiated type.
inherited from Applicative.*>
inherited from Applicative.<*
inherited from Monad.<*>
inherited from Monad.>>
inherited from Monad.join
inherited from Applicative.*>
inherited from Applicative.<*
inherited from Monad.<*>
inherited from Monad.fmap
inherited from Monad.join
inherited from Applicative.*>
inherited from Applicative.<*
inherited from Monad.<*>
monadic bind for the State monad
inherited from Monad.fmap
inherited from Monad.join
lift a value to the State monad
inherited from Applicative.*>
inherited from Applicative.<*
inherited from Monad.<*>
inherited from Monad.>>
inherited from Monad.join
An infix synonym for Functor.fmap. Left associative with precedence 4.
Right-to-left Kleisli composition of monads. (>=>), with the arguments flipped
left to right Kleisli composition of monads
In many situations, the liftM operations can be replaced by uses of ap, which promotes function application.
return f `ap` x1 `ap` ... `ap` xn
is equivalent to
liftMn f x1 x2 ... xn
foldM f a xs folds a monadic function f over the list xs.
foldM_ is the same as foldM, but discards the result
forM xs f = mapM_ f xs
repeat action forever
guard b is return () if b is true, and MonadZero.mzero otherwise.
Promote a function to a monad.
Promote a function to a monad, scanning the monadic arguments from left to right. For example,
liftM2 (+) [0,1] [0,2] = [0,2,1,3]
liftM2 (+) (Just 1) Nothing = Nothing
Promote a function to a monad, scanning the monadic arguments from left to right (cf. liftM2).
Promote a function to a monad, scanning the monadic arguments from left to right (cf. liftM2).
Promote a function to a monad, scanning the monadic arguments from left to right (cf. liftM2).
The mapAndUnzipM function maps its first argument over a list, returning the result as a pair of lists. This function is mainly used with complicated data structures or a state-transforming monad.
mapM f is equivalent to sequence • map f
mapM_ f is equivalent to sequence_ • map f
replicateM n act performs the action n times, gathering the results.
Like replicateM, but discards the result.
Turn a list of monadic values [m a] into a monadic value with a list m [a]
sequence [Just 1, Just 3, Just 2] = Just [1,2,3]
This version of sequence runs in constant stack space, but needs heap space proportional to the size of the input list.
foldr (Monad.>>) over a list of monadic values for side effects
opposite of when
discard or ignore result of evaluation, such as the return value of an IO action.
when condition monadic returns /action/ of type Monad m => m () if /condition/ is true, otherwise Applicative.return ().
The zipWithM function generalizes zipWith to arbitrary monads.
zipWithM_ is the extension of zipWithM which ignores the final result.