Mar*_*olo 4 monads haskell functional-programming
我有这个简单的代码:
module Matrix where
matrix :: a -> (Int, Int) -> [[a]]
matrix x (width, height) = replicate height (replicate width x)
mapMatrix :: (a -> b) -> [[a]] -> [[b]]
mapMatrix f m = map (map f) m
Run Code Online (Sandbox Code Playgroud)
当我做:
mapMatrix (+1) (matrix 0 (2,2))
Run Code Online (Sandbox Code Playgroud)
我得到了,如预期的那样:
[[1,1],[1,1]]
可能我误解了monad和/或>>=运算符,但我希望以下内容具有相同的输出:
matrix 0 (2,2) >>= mapMatrix (+1)
Run Code Online (Sandbox Code Playgroud)
相反,我得到:
约束中的非类型变量参数:Num [b](使用FlexibleContexts允许此操作)当检查推断类型It :: forall b时.(Num [b],Num b)=> [[b]]
我怎么能用mapMatrix (+1) (matrix 0 (2,2))monad 写,所以我可以从左到右读取和编写代码而不是从内到外,因为你可以想象,我打算在mapMatrix同一个矩阵上使用很多东西,比如:
matrix ... >>= mapMatrix ... >>= mapMatrix .. >>= ...
Run Code Online (Sandbox Code Playgroud)
这不是monad应该做的.您可能对(&) :: a -> (a -> b)定义的内容感兴趣Data.Function.
matrix ... & mapMatrix ... & mapMatrix .. & ...
Run Code Online (Sandbox Code Playgroud)
请注意绑定的签名是
(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
一个人不能简单地忽略ms.
为了完整性,请注意,实际上可以使绑定的行为几乎与您希望它使用一个特定monad的方式相同:Identity.它需要一些包装/展开构造函数.
module Matrix where
import Data.Functor.Identity
matrix :: a -> (Int, Int) -> Identity [[a]]
matrix x (width, height) = Identity $ replicate height (replicate width x)
mapMatrix :: (a -> b) -> [[a]] -> Identity [[b]]
mapMatrix f m = Identity $ map (map f) m
Run Code Online (Sandbox Code Playgroud)
然后,以下工作也是如此:
runIdentity (matrix ... >>= mapMatrix ... >>= mapMatrix .. >>= ...)
Run Code Online (Sandbox Code Playgroud)