Expressing do block using only monadic bind syntax

后端 未结 2 1934
难免孤独
难免孤独 2020-12-02 02:18

As far as I know, do blocks in Haskell are just some kind of syntactic sugar for monadic bind operators. For example, one could convert



        
相关标签:
2条回答
  • 2020-12-02 02:26

    Yes, all of them can be converted to bind syntax; in fact, they are converted internally by the compiler.

    I hope this translation of your example gives you the hint:

    main = readFile "foo.txt" >>= \f ->
           (print $ "prefix " ++ f) >>
           (print $ f ++ " postfix")
    
    0 讨论(0)
  • 2020-12-02 02:49

    The Report gives a full translation from do syntax into kernel Haskell:

    Do expressions satisfy these identities, which may be used as a translation into the kernel, after eliminating empty stmts:

    do {e}                = e
    do {e;stmts}          = e >> do {stmts}
    do {p <- e; stmts}    = let ok p = do {stmts}
                                ok _ = fail "..."
                            in e >>= ok
    do {let decls; stmts} = let decls in do {stmts}
    

    The ellipsis "..." stands for a compiler-generated error message, passed to fail, preferably giving some indication of the location of the pattern-match failure; the functions >>, >>=, and fail are operations in the class Monad, as defined in the Prelude; and ok is a fresh identifier.

    So your example translates this way:

    do f <- readFile "foo.txt"
       print $ "prefix " ++ f
       print $ f ++ " postfix"
    =
    let ok f = do print $ "prefix " ++ f
                  print $ f ++ " postfix"
        ok _ = fail "..."
    in readFile "foo.txt" >>= ok
    =
    let ok f = (print $ "prefix " ++ f) >> do print $ f ++ " postfix"
        ok _ = fail "..."
    in readFile "foo.txt" >>= ok
    =
    let ok f = (print $ "prefix " ++ f) >> (print $ f ++ " postfix")
        ok _ = fail "..."
    in readFile "foo.txt" >>= ok
    

    This version has no do blocks, but doesn't look very natural. But we can apply equational reasoning and whatever optimizations we know. So, for example, observing that the ok _ = fail "..." clause is dead code, we could inlike ok like so:

     =
     readFile "foo.txt" >>= \f ->
     (print $ "prefix " ++ f) >>
     (print $ f ++ " postfix")
    

    All do blocks can be mechanically translated into code without do in this way.

    0 讨论(0)
提交回复
热议问题