Jump to content

User:Metaquanta/sandbox

From Wikipedia, the free encyclopedia

This is the current revision of this page, as edited by Metaquanta (talk | contribs) at 20:11, 9 February 2021 (monad example to de-haskelize). The present address (URL) is a permanent link to this version.

(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

An example: Maybe

[edit]

To motivate programming with monads, here is a quick pseudocode example. Undefined values or operations are one particular problem that robust software should prepare for and handle gracefully.

The first step toward this goal might be to create an option type that will mark a value as either carrying a value of some type T (T can be any type) or carrying no value. The new type will be called Maybe T and values of that type can either contain a value of type T, or be the empty value Nothing. A value X of type T which is defined but used in the context of Maybe will be called Just X. This is done to avoid confusion by differentiating between cases where a variable carries a defined value and those where it does not.

data Maybe T  =  Just T or Nothing

Maybe T can be understood as a "wrapping" type, wrapping the type T into a new type with built-in exception handling, though carrying no information about the cause of an exception.

In the following code, variables prefixed with m have the type Maybe T for some type T. For example, if a variable mx contains a value, it is Just x, where the variable x has the type T. λx → ... is an anonymous function with the parameter x whose type is inferred, and is the function composition operator.

Another improvement would be if a function could manage simple checked exceptions with a Maybe type, short-circuiting and returning Nothing once a step fails, but returning the correct value without comment if a calculation succeeds.

An addition function add, which does exactly this when adding two Maybe values, mx and my, can be defined like so:

 add : (Maybe Number, Maybe Number)  Maybe Number
 add(mx,my) = ...
     if mx is Nothing then
         ... Nothing
     else if my is Nothing then
         ... Nothing
     else
         ... Just (x + y)
     end if

Writing functions that process Maybe values case-by-case can be tedious though, and will only become more so as more functions are defined. An operation to chain steps together is one way to alleviate this, and with an infix operator like x >>= y, it can even intuitively represent feeding the (possibly undefined) result from each step into the next. Since each result is technically inserted into another function, however, the operator will take a function for a parameter. As add already specifies the type of its output value, it should not hurt to keep the operator flexible and accept functions that output different types from their input:

 >>= : (Maybe T, T  Maybe U)  Maybe U
 (mx >>= f) = ...
     if mx is (Just x) then
         ... f(x)    -- f returns a defined value of type Maybe U
     else
         ... Nothing -- f returns no value
     end if

With >>= available, add can now be redefined as something much more compact:

 add(mx,my)  =  mx >>= λx -> (my >>= λy -> Just (x + y))

This is more concise, but a little extra analysis reveals something even more powerful. For one, the only role that Just plays in add is to tag an underlying value as also being a Maybe value. To emphasize how Just acts on the underlying value by wrapping it, it can be redefined as a function too, called eta for now:

 eta : T  Maybe T
 eta(x)  =  Just x

The big picture is that these two functions >>= and eta were designed to simplify add, but they clearly do not depend on the specifics of add in any way, just the Maybe type. These functions can, in fact, apply to any values and functions of the Maybe type, regardless of the underlying values' types. For example, here is a concise NOT operator from (Kleene's) trinary logic that uses the same functions to automate undefined values too:

trinot : Maybe Boolean  Maybe Boolean
trinot(mp)  =  mp >>= λp -> (eta  not) p

It turns out the Maybe type, together with >>= and eta, forms a monad. While other monads will embody different logical processes, and some may have extra properties, all of them will have three similar components (directly or indirectly) that follow the basic outline of this example.[1][2]

  1. ^ Cite error: The named reference RealWorldHaskell was invoked but never defined (see the help page).
  2. ^ Spivey, Mike (1990). "A functional theory of exceptions" (PDF). Science of Computer Programming. 14 (1): 25–42. doi:10.1016/0167-6423(90)90056-J.