Haskell Monad(下)

Posted 牛顿一号

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Haskell Monad(下)相关的知识,希望对你有一定的参考价值。

Haskell中的Monad(下)

这里先放上篇中关于eval的monad实现代码,在ghc 8.2.2中验证通过。

上篇相关代码实现

basic monadic eval

 1{- basic eval -}
2data Term = Con Int | Div Term Term
3{-Monadic Evaluation Function -}
4type M a = a
5unit :: a -> M a
6unit = id
7(>>>) :: M a -> (a -> M b) -> M b
8a >>> k = k a
9eval :: Term -> M Int
10eval (Con a) = unit a
11eval (Div t u) = eval t >>> \x -> eval u >>> \y -> unit (round (fromIntegral x/ fromIntegral y))
12

带异常处理的monadic eval。

 1{- Monadic Eval with Exception Handling -}
2data Term = Con Int | Div Term Term
3data M a = Raise Exception | Return a deriving (Show)
4type Exception = String
5unit :: a -> M a
6unit a = Return a
7(>>>) :: M a -> (a -> M b) -> M b
8m >>> k = case m of
9  Raise e -> Raise e
10  Return a -> k a
11raise :: Exception -> M a
12raise e = Raise e
13eval :: Term -> M Int
14eval (Con a) = unit a
15eval (Div t u) = eval t >>> \x -> eval u >>> \y -> if y == 0
16  then raise "divide by zero"
17  else unit (round (fromIntegral x/ fromIntegral y))

带状态的monadic eval

 1{- Monadic Eval with State Handling -}
2data Term = Con Int | Div Term Term
3type M a = State -> (a, State)
4type State = Int
5unit :: a -> M a
6unit a = \x -> (a, x)
7(>>>) :: M a -> (a -> M b) -> M b
8m >>> k = \x -> let (a,y) = m x in
9                let (b,z) = k a y in (b,z)
10tick :: M ()
11tick = \x -> ((), x+1)
12eval :: Term -> M Int
13eval (Con a) = unit a
14eval (Div t u) = eval t >>> \x -> eval u >>> \y -> tick >>> \_ -> unit(round (fromIntegral x/ fromIntegral y))

带状态的monadic eval运行结果。

1*Main> eval (Div (Con 10) (Div (Con 4) (Con 2))) 0
2*Main> (5,2)

带trace功能的monadic eval。

 1{- Monadic Eval with Tracing -}
2data Term = Con Int | Div Term Term deriving (Show)
3type M a = (Output,a)
4type Output = String
5unit :: a -> M a
6unit a = ("", a)
7(>>>) :: M a -> (a -> M b) -> M b
8m >>> k = let (x,a) = m in
9          let (y,b) = k a in
10          (y++x, b)
11out :: Output -> M ()
12out x = (x,())
13eval :: Term -> M Int
14eval (Con a) = out (show (Con a)) >>> \_ -> unit(a)
15eval (Div t u) = eval t >>> \x -> eval u >>> \y -> out (show (Div t u)) >>> \_ -> unit(round (fromIntegral x/ fromIntegral y))

output monad运行结果。

1*Main> eval (Con 2)
2("Con 2",2)
3*Main> eval (Div (Con 10) (Con 5))
4("Con 10Con 5Div (Con 10) (Con 5)",2)
5#x++y -> y++x后
6*Main> eval (Div (Con 10) (Con 5))
7("Div (Con 10) (Con 5)Con 5Con 10",2)
8*Main>


以上是关于Haskell Monad(下)的主要内容,如果未能解决你的问题,请参考以下文章

从 Haskell 到 JavaScript 的翻译,我读过的最好的 Monad 介绍的部分内容

在haskell中构建一个非确定性的monad转换器

在 Haskell 中使用 Logic Monad

Haskell:使用 List Monad 计算周期

为啥 Haskell 异常只能在 IO monad 中捕获?

Monad_Haskell笔记10