Difference between revisions of "Merely monadic"
(Comment about monad laws relocated from 'Monad') 
m (Incorrect link replaced #:<) 

(3 intermediate revisions by the same user not shown)  
Line 1:  Line 1:  
−  '''''Monads''''' in Haskell can be thought of as ''composable'' computation descriptions. The essence of monad is thus ''separation'' of ''composition timeline'' from the composed computation's ''execution timeline'', as well as the ability of ''computation'' to implicitly carry extra data, as pertaining to the computation itself, in addition to its ''one'' (hence the name) output, that it '''''will produce''''' when run (or queried, or called upon). This lends monads to supplementing ''pure'' calculations with features like I/O, common environment, updatable state, etc. 

+  == Introduction == 

−  Each monad, or computation type, provides means, subject to '''''Monad Laws''''', to 

+  In Haskell, ''monadic types''  types having an instance for the <code>Monad</code> class  can be thought of as ''abstract descriptors'' of ''computations'' which are inherently ''composable''  smaller monadic expressions (''actions'') can be used to build larger ones. 

−  * '''''(a)''''' ''create'' a description of a computation that will produce (a.k.a. "return") a given Haskell value, and 

+  This ''monadic interface'' (as specified by <code>Monad</code>) provides actions additional flexibility in separating: 

−  * '''''(b)''''' ''combine'' (a.k.a. "bind") a computation description with a ''reaction'' to it, – a pure Haskell function that is set to receive a computationproduced value (when and if ''that'' happens) and return another computation description, using or dependent on that value if need be, – creating a description of a combined computation that will feed the original computation's output through the reaction while automatically taking care of the particulars of the computational process itself. 

+  * the ''time of composition'': when it is defined; 

−  ''Reactions'' are thus computation description ''constructors''. A monad might also define additional primitives to provide access to and/or enable manipulation of data it implicitly carries, specific to its nature; cause some specific sideeffects; etc. As for the [[Monad lawsmonad laws]], they basically say that a monad's reactions should be associative under Kleisli composition, defined as <code>(f >=> g) x = f x >>= g</code>, with <code>return</code> its left and right identity element. 

+  * the ''time of execution'': when it is used; 

−  Sometimes the specific monadic type also provides the ability to somehow '''''(c)''''' ''run'' a computation description, getting its result back into Haskell if computations described by the monad are pure, but this is expressly '''''not''''' a part of the Monad interface. Officially, <i>you can't get the <hask>a</hask> out of <hask>M a</hask></i> directly, only arrange for it to be "fed" into the next computation's constructor, the "reaction", indirectly. In case of an <hask>IO</hask> monad value, a computation it describes runs implicitly as a part of the chain of I/O computation descriptions composed together into the value <hask>main</hask> (of type <hask>IO ()</hask>) in a given Haskell program, by convention. <! Put simply, it runs when the compiled program runs (but then, everything does). > 

+  * the ''mode of computation'': what else it can do, in addition to emitting its ''single'' (hence the name) output value. 

−  <haskell style="backgroundcolor:#f8f1ab;borderradius:15px;border:2px solid #000000;padding:15px"> 

+  == Monadic operations == 

−  # Monad interactions: 

−  (a) reaction $ value ==> computation_description 

+  Ideally, each monadic type in Haskell should satisfy the ''[[Monad Lawsmonad laws]]'' by providing two basic operations: 

−  (b) reaction =<< computation_description ==> computation_description 

+  * <code>return :: Monad m => a > m a</code>: 

+  :{ 

+   argument 

+   <code>:: a</code> 

+   another Haskell value 

+   

+   result 

+   <code>:: m a</code> 

+   an action, merely ''returning'' the argument's value. 

+  } 

−  (c) reaction $ computation_description ==> ***type_mismatch*** 

+  * <code>(>>=) :: Monad m => m a > (a > m b) > m b</code>: 

+  :{ 

+   argument #1 

+   <code>:: m a</code> 

+   an action 

+   

+   argument #2 

+   <code>:: (a > m b)</code> 

+   a suitable Haskell function (a ''reaction'') 

+   

+   result 

+   <code>:: m b</code> 

+   <p>another action, the result of ''binding'' the output value of argument #1<br> 

+  (the action) to the input of argument #2 (the reaction).</p> 

+  } 

+  Together, these two operations allow many of the specific (and oftenrepetitive) details of the computational processes used by actions to be abstracted away. This often makes the monadic interface the preferred choice for ''abstract data types'', where the inner workings of monadic actions must be kept private e.g. to ensure they work as intended. 

−  (d) reaction <$> computation_description ==> computation_description_description 

+  As a reaction uses its argument to build a new monadic result, it can be thought of as an abstract ''constructor'' for new actions. In this way <code>return</code> can then be seen as the trivialaction constructor for new actions: the monadic counterpart to the identity function <code>Prelude.id</code>: 

−  (e) join $ computation_description_description ==> computation_description 

+  <haskell> 

+  id :: a > a 

+  id x = x 

</haskell> 
</haskell> 

−  (<i><hask>join</hask></i> is another function expressing the essence of monad; where <hask>m >>= k = k =<< m = join (k <$> m) = join (fmap k m)</hask>; it is prefered in mathematics, over the ''bind''; both express the same concept). 

+  === <code>IO</code>, in particular === 

−  Thus in Haskell, though it is a purelyfunctional language, side effects that '''''will be performed''''' by a computation can be dealt with and combined ''purely'' at the monad's composition time. Monads thus resemble programs in a particular [[EDSL]] (''embedded'' domainspecific language, "embedded" because the values denoting these computations are legal Haskell values, not some extraneous annotations). 

+  The <code>IO</code> type is special because a Haskell program is one large <code>IO</code> action (usually) called <code>main</code>  for any other <code>IO</code> action to work, it should be part of the chain of I/O actions composed together to form <code>main</code>. Execution of a Haskell program then starts by the Haskell implementation calling <code>main</code>, according to the implementation's private definition of the abstract <code>IO</code> type. 

−  While programs may describe impure effects and actions ''outside'' Haskell, they can still be combined and processed (''"assembled"'') purely, ''inside'' Haskell, creating a pure Haskell value  a computation action description that describes an impure calculation. That is how Monads in Haskell help keep the ''pure'' and the ''impure'' apart. 

+  == Using monadic actions == 

−  The computation doesn't have to be impure and can be pure itself as well. Then monads serve to provide the benefits of separation of concerns, and automatic creation of a computational "pipeline". 

+  Assuming: 

+  
+  * <code>M</code> is a monadic type; 

+  
+  * <code>x :: a</code> is some other Haskell value; 

+  
+  * <code>m :: M a</code> is an action; 

+  
+  * <code>k :: (a > M b)</code> is a reaction; 

+  
+  * <code>M</code>, <code>x</code>, <code>m</code>, <code>k</code> are ''wellbehaved''; 

+  
+  then: 

+  
+  { 

+   (a) 

+   <code>r1 = k $ x</code> 

+   <code> :: M b</code> 

+   (''a new action'') 

+   

+   (b) 

+   <code>r2 = return x</code> 

+   <code> :: M a</code> 

+   (''an action whose output value is'' <code>x</code>) 

+   

+   (c) 

+   <code>r3 = m >>= k</code> 

+   <code> :: M b</code> 

+   (''another new action'') 

+   

+   (d) 

+   <code>r4 = k =<< m</code> 

+   <code> :: M b</code> 

+   (''the same as'' <code>r3</code>) 

+   

+   (e) 

+   <code>r5 = k $ m</code> 

+   '''(''types don't match'')''' 

+   

+   

+   (f) 

+   <code>r6 = k <$> m</code> 

+   <code> :: M (M b)</code> 

+   (''an action whose output value is also the same as'' <code>r3</code>) 

+   

+   (g) 

+   <code>r7 = join (k <$> m)</code> 

+   <code> :: M b</code> 

+   (''the same as'' <code>r3</code>) 

+  } 

+  
+  where: 

+  
+  <haskell> 

+  infixr 0 $ 

+  ($) :: (a > b) > a > b 

+  f $ x = f x 

+  
+  infixr 1 =<< 

+  (=<<) :: (a > M b) > M a > M b 

+  k =<< m = m >>= k 

+  
+  infixl 4 <$> 

+  (<$>) :: (a > b) > M a > M b 

+  f <$> m = m >>= \x > return (f x) 

+  
+  join :: M (M a) > M a 

+  join m = m >>= \x > x 

+  </haskell> 

+  
+  Even though it is a purelyfunctional language, Haskell can facilitate the use of effectbased computations by presenting them as monadic actions (using a suitable type), with the monadic interface helping to maintain purity. This is the result of the aformentioned separation of concerns, most notably the ''time of composition''. Monadic actions thus resemble programs in a particular [[EDSL]] (''embedded'' domainspecific language), "embedded" because they are legitimate Haskell values which ''describe'' impure computations  no extraneous annotations are needed. This is how monadic types in Haskell help keep the ''pure'' and the ''impure'' apart. But not all monadic actions are impure  for them, the benefits of separating concerns are often combined with the automatic formation of a computational "pipeline". 

+  
+  Because they are very useful in practice but rather confronting for beginners, numerous [[Monad tutorials timelinemonad tutorials]] (including this one) exist to help with the learning process. 

+  
+  == Supplemental operations for monadic types (''nonstandard morphisms'') == 

+  
+  In addition to the two basic ones required by the monadic interface, each monadic type can have its own specific operations e.g. to provide access to and/or enable manipulation of data it implicitly carries which is specific to its nature; cause some specific sideeffects; etc. 

+  
+  === Running monadic actions === 

+  
+  Some monadic types provide an extra operation for ''running'' actions, usually if they are ''purely'' defined by the type. This allows an action's output value to be obtained directly in Haskell, in contrast to <code>(>>=)</code>. While some of the predefined (e.g. from the <code>Prelude</code>) monadic types in Haskell have such an operation (e.g. <code>Prelude.maybe</code> or <code>Prelude.either</code>), most do not. 

+  
+  Why this is expressly '''''not''''' a part of the monadic interface by now should be obvious  impure monadic actions could then be "hidden" inside seeminglypure definitions, which would end any notion of purity in Haskell. This is why the only generalpurpose way to use a monadic action's output value is to direct it to subsequent computations via the reaction which constructs them, through the use of <code>(>>=)</code>. 

[[Category:Monad]] 
[[Category:Monad]] 
Latest revision as of 04:35, 16 March 2021
Contents
Introduction
In Haskell, monadic types  types having an instance for the Monad
class  can be thought of as abstract descriptors of computations which are inherently composable  smaller monadic expressions (actions) can be used to build larger ones.
This monadic interface (as specified by Monad
) provides actions additional flexibility in separating:
 the time of composition: when it is defined;
 the time of execution: when it is used;
 the mode of computation: what else it can do, in addition to emitting its single (hence the name) output value.
Monadic operations
Ideally, each monadic type in Haskell should satisfy the monad laws by providing two basic operations:

return :: Monad m => a > m a
:
argument :: a
another Haskell value result :: m a
an action, merely returning the argument's value.

(>>=) :: Monad m => m a > (a > m b) > m b
:
argument #1 :: m a
an action argument #2 :: (a > m b)
a suitable Haskell function (a reaction) result :: m b
another action, the result of binding the output value of argument #1
(the action) to the input of argument #2 (the reaction).
Together, these two operations allow many of the specific (and oftenrepetitive) details of the computational processes used by actions to be abstracted away. This often makes the monadic interface the preferred choice for abstract data types, where the inner workings of monadic actions must be kept private e.g. to ensure they work as intended.
As a reaction uses its argument to build a new monadic result, it can be thought of as an abstract constructor for new actions. In this way return
can then be seen as the trivialaction constructor for new actions: the monadic counterpart to the identity function Prelude.id
:
id :: a > a
id x = x
IO
, in particular
The IO
type is special because a Haskell program is one large IO
action (usually) called main
 for any other IO
action to work, it should be part of the chain of I/O actions composed together to form main
. Execution of a Haskell program then starts by the Haskell implementation calling main
, according to the implementation's private definition of the abstract IO
type.
Using monadic actions
Assuming:

M
is a monadic type;

x :: a
is some other Haskell value;

m :: M a
is an action;

k :: (a > M b)
is a reaction;

M
,x
,m
,k
are wellbehaved;
then:
(a)  r1 = k $ x

:: M b

(a new action) 
(b)  r2 = return x

:: M a

(an action whose output value is x )

(c)  r3 = m >>= k

:: M b

(another new action) 
(d)  r4 = k =<< m

:: M b

(the same as r3 )

(e)  r5 = k $ m

(types don't match)  
(f)  r6 = k <$> m

:: M (M b)

(an action whose output value is also the same as r3 )

(g)  r7 = join (k <$> m)

:: M b

(the same as r3 )

where:
infixr 0 $
($) :: (a > b) > a > b
f $ x = f x
infixr 1 =<<
(=<<) :: (a > M b) > M a > M b
k =<< m = m >>= k
infixl 4 <$>
(<$>) :: (a > b) > M a > M b
f <$> m = m >>= \x > return (f x)
join :: M (M a) > M a
join m = m >>= \x > x
Even though it is a purelyfunctional language, Haskell can facilitate the use of effectbased computations by presenting them as monadic actions (using a suitable type), with the monadic interface helping to maintain purity. This is the result of the aformentioned separation of concerns, most notably the time of composition. Monadic actions thus resemble programs in a particular EDSL (embedded domainspecific language), "embedded" because they are legitimate Haskell values which describe impure computations  no extraneous annotations are needed. This is how monadic types in Haskell help keep the pure and the impure apart. But not all monadic actions are impure  for them, the benefits of separating concerns are often combined with the automatic formation of a computational "pipeline".
Because they are very useful in practice but rather confronting for beginners, numerous monad tutorials (including this one) exist to help with the learning process.
Supplemental operations for monadic types (nonstandard morphisms)
In addition to the two basic ones required by the monadic interface, each monadic type can have its own specific operations e.g. to provide access to and/or enable manipulation of data it implicitly carries which is specific to its nature; cause some specific sideeffects; etc.
Running monadic actions
Some monadic types provide an extra operation for running actions, usually if they are purely defined by the type. This allows an action's output value to be obtained directly in Haskell, in contrast to (>>=)
. While some of the predefined (e.g. from the Prelude
) monadic types in Haskell have such an operation (e.g. Prelude.maybe
or Prelude.either
), most do not.
Why this is expressly not a part of the monadic interface by now should be obvious  impure monadic actions could then be "hidden" inside seeminglypure definitions, which would end any notion of purity in Haskell. This is why the only generalpurpose way to use a monadic action's output value is to direct it to subsequent computations via the reaction which constructs them, through the use of (>>=)
.