给定addStuff
addStuff :: Int -> Int
addStuff = do
a<-(*2)
b<-(+10)
return (a+b)
定义脱糖成
addStuff =
(* 2) >>= \a ->
(+ 10) >>= \b ->
return (a + b)
将鼠标悬停>>=
在fpcomplete 在线编辑器显示
:: Monad m => forall a b.
(m a ) -> (a -> m b ) -> (m b )
:: (Int -> a ) -> (a -> Int -> b ) -> (Int -> b )
:: (Int -> Int) -> (Int -> Int -> Int) -> (Int -> Int)
这使我们相信我们将 Monad 实例用于函数。确实,如果我们查看源代码,我们会看到
instance Monad ((->) r) where
return = const
f >>= k = \ r -> k (f r) r
使用这些新获得的信息,我们可以自己评估addStuff
函数。
给定初始表达式
(* 2) >>= ( \a -> (+10) >>= \b -> return (a + b) )
我们用定义代替,>>=
给我们(在下面{}
,,,只是说明不同的深度)[]
()
()
\r1 -> {\a -> (+10) >>= \b -> return (a + b)} {(* 2) r1} r1
简化最外层 lambda 内的倒数第二项
\r1 -> {\a -> (+10) >>= \b -> return (a + b)} {r1 * 2} r1
适用{r1 * 2}
于{\a -> ...}
\r1 -> {(+10) >>= \b -> return ((r1 * 2) + b)} r1
>>=
再次用其定义替换剩余
\r1 -> {\r2 -> [\b -> return (r1 * 2 + b)] [(+10) r2] r2} r1
简化内部 lambda 中的倒数第二项
\r1 -> {\r2 -> [\b -> return (r1 * 2 + b)] [r2 + 10] r2} r1
适用[r2 + 10]
于{\b -> ...}
\r1 -> {\r2 -> [return (r1 * 2 + (r2 + 10))] r2} r1
适用r1
于{\r2 -> ...}
\r1 -> {return (r1 * 2 + r1 + 10) r1}
return
用它的定义代替
\r1 -> {const (r1 * 2 + r1 + 10) r1}
评估const x _ = x
\r1 -> {r1 * 2 + r1 + 10}
美化
\x -> 3 * x + 10
最后我们得到
addStuff :: Int -> Int
addStuff = (+ 10) . (* 3)