Questions tagged [do-notation]

In Haskell, do-notation is syntactic sugar for writing monadic code, expressing computations as sequences of monadic actions. Every participant monadic value in the do block must belong to the same monad.

In Haskell, do-notation is syntactic sugar for writing monadic code expressing computations as sequences of monadic actions, each action possibly calculated -- purely -- from the preceding action's computed results.

Every participant monadic value in the same do block must belong to the same monad.

do-notation explained, in vivid colors.

do blocks translate into monadic code, but we can view this fact as implementational detail, at first. We can treat the do notation axiomatically, as an embedded language.

do blocks express sequences of monadic "actions". A simplified, standardized do-syntax is:

   do {  pattern1 <- action1
      ;  pattern2 <- action2
      ;  pattern3 <- action3
      .....................
      ;  return result
      }

Each actioni is a Haskell expression of type M ai for some monad M and some result type ai, with M the same for all is. (Examples are: Maybe a, Maybe b, Maybe c; [a], [b], [c]; IO a, IO b, IO c; etc.)

Thus each actioni "produces" its own result type ai "in" the same monad M as all the other actions in the do block.

The overall type of a do block expression is M an where an is the type of the argument result in the final return result action (which thus has the type M an). Put differently, the type of the final action in the do block is the type of the overall do block.

In particular (and a frequent cause of confusion while learning), if actioni is an if expression, each of its branches must be an expression of the same M ai type, an expression that itself could be a do block, if it needs to sequence several M actions.

Each patterni becomes match-bound to the "computed" result from the corresponding actioni, when the whole combined "computation" described by the whole do block actually "runs" (whatever that means specifically, for the specific M type). If the pattern is refutable, and the pattern match fails, the do computation chain is aborted through the invocation of M's fail method; otherwise, the computation chain continues to the next do line.

Each patterni's variable is in scope from the point of its introduction and to the end of the do block. In particular this means that the result expression in the final return result action may refer to any of the patterni's variables, as may any actionj where j > i.

It also means that the binding construct <- is non-recursive: the scope to its right (and above) contains the scope to its left (and below). That in turn means that if any variable is bound more than once, the deeper (nested) binding shadows the outer binding -- any use of a variable's name refers to its most recent binding only.

Wildcards _ can be used to ignore the computed value. If this is the case, the _ <- part can be omitted altogether.

Another special case is that by Monad laws, do { .... ; x <- action ; return x } is equivalent to do { .... ; action }.

The translation of a do code into actual monadic code goes by the rule

   do { pat <- act ; ... }
===
   act >>= f  where
           f pat = do { ... }
           f _   = fail "error-message"

and

   do { act }
===
   act

Optionally, let can also appear in a do block, which has a simple syntax re-write:

   do { actions... 
      ; let {...}          -- no "in", NB!
      ; more_actions...
      }
===
   do { actions...
      ; let {...} 
        in
          do { more_actions... }
      }
159 questions
0
votes
1 answer

do notation magically fixes an otherwise refused expression as argument

In Nim templates: as a follow-up from this problem, I had the idea of working around the default-argument unavailability by using overloading, or even in this case, plain wrapping. Though, it would be too good if something didn't hit the fan again,…
v.oddou
  • 6,476
  • 3
  • 32
  • 63
0
votes
1 answer

Haskell Errors Binding a CSV File to a Handle

So I was writing a small toybox of utility functions for CSV files and throughout testing the functions I'd been binding the file by hand with table' <- parseCSVFromFile filepath but (from Text.CSV) parseCSVFromFile :: FilePath -> IO (Either…
Tshimanga
  • 845
  • 6
  • 16
0
votes
1 answer

Using (_ <- f) instead of f Alone?

Looking at this ZeroMQ HelloWorldClient.hs code snippet: forM_ [1..10] $ \i -> do liftIO . putStrLn $ "Sending Hello " ++ show i ++ "…" send requester [] "Hello" _ <- receive requester liftIO . putStrLn $ "Received World " ++ show…
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
0
votes
2 answers

How can I return a Maybe value from do notation in PureScript?

I'm trying to return a Maybe value from a function that uses do notation, but I can't seem to get it to work. This function takes a string (The "filename") and a Path to search in... findIn :: String -> Path -> Maybe Path findIn search start = do …
Albtzrly
  • 924
  • 1
  • 6
  • 15
0
votes
1 answer

Haskell: trailing right arrow in a bind operation

From haskellwiki: expr1 >>= \x -> I am curious about the right side of the (>>=) operator \x ->. What does it mean? Nor \x -> nor \x is recognized by :type in GHCi.
xged
  • 1,207
  • 1
  • 14
  • 20
-1
votes
2 answers

Haskell: Compute Cycles with List Monad

-- 1. Graph structure: nodes and adjacency matrix (i.e. the edges) data Node = A | B | C | D | E | F deriving (Show,Eq,Ord) adj :: (Node,Node) -> Bool adj p = case p of (A,B) -> True (A,C) -> True (B,C) -> True (B,F) -> True (C,D) ->…
-1
votes
1 answer

how to use do and while loop in haskell

I tried to use an addition and print every step, but it doesn't work, can someone help me out please? addition x = x+1 acc_addition xs = do print xs let result = addition xs if result == 5 …
Andy Tsao
  • 33
  • 2
-1
votes
1 answer

Haskell error load module with mysql

Haskell : Database.MySQL.Base insert_Producto = do conn <- connect defaultConnectInfo {ciUser = "root", ciPassword = "", ciDatabase = "prueba"} oks <- executeMany conn "delete from producto" load Module : Conexion.hs:27:5: error: …
-2
votes
1 answer

Haskell - How do I nest multiple if statements containing multiple putStrLn satatements

This is the gist of the problem: check_if_proceed configFolders = do let emacsdf = "/home/jacek/.emacs.d" traceM ("calling check_if_proceed " ++ show ("ccc",configFolders)) exists <- doesDirectoryExist emacsdf symlink <- pathIsSymbolicLink…
ruby_object
  • 1,229
  • 1
  • 12
  • 30
1 2 3
10
11