附加monad

Cli*_*ton 0 monads haskell

只是putChar我可以做这样的事情:

f = 
  do
    putChar 'a'
    putChar 'b'
    g
    putChar 'f'
    putChar 'g'

g =
  do
    putChar 'c'
    putChar 'd'
    putChar 'e'
Run Code Online (Sandbox Code Playgroud)

当我"跑"这个(通过说main = f)时我会发现它只是按顺序打印出来的字符.

我正在寻找的是非IO版本.有点像这样的东西:

f = 
  do
    append 'a'
    append 'b'
    g
    append 'f'
    append 'g'

g =
  do
    append 'c'
    append 'd'
    append 'e'
Run Code Online (Sandbox Code Playgroud)

而且还有一个功能 runAppend :: t a -> [a]

这样runAppend f=['a','b','c','d','e','f','g']

当然,我希望它在线性时间内运行(即不会遇到类似于++以错误顺序进行连接的问题).

这似乎是一个相当常见的用例,所以我猜它存在,如果有人能指出我会那么好,我不想重新发明轮子.

Dan*_*ner 9

作家单子做到这一点:

> let g = tell "b" >> tell "c" >> tell "d"
> runWriter (tell "a" >> g >> tell "e")
((),"abcde")
Run Code Online (Sandbox Code Playgroud)


Cac*_*tus 7

您可以使用Writermonad:

import Control.Monad.Writer
import Data.DList (DList)
import qualified Data.DList as DList

type Append c = Writer (DList c)

append :: c -> Append c ()
append = tell . pure

runAppend :: Append c () -> [c]
runAppend = DList.toList . execWriter

f, g :: Append Char ()
Run Code Online (Sandbox Code Playgroud)

这比必要的要复杂一点,因为它使用的是a DList Char而不是a String.为这种情况DList提供了一个有效的Monoid实例,您可以继续追加到最后.