我有这个简单的代码:
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
当我这样做时:
mapMatrix (+1) (matrix 0 (2,2))
我得到了,正如所料:
[[1,1],[1,1]]
可能我误解monad和/或>>=
运算符,但我期望以下内容具有相同的输出:
matrix 0 (2,2) >>= mapMatrix (+1)
相反,我得到:
约束中的非类型变量参数:Num [b] (使用FlexibleContexts允许此操作)检查推断类型时 它:: forall b。 (Num [b],Num b)=> [[B]]
如何用monad编写mapMatrix (+1) (matrix 0 (2,2))
,这样我就可以从左到右而不是从内到下读写代码,因为你可以想象,我正计划使用{{ 1}}在同一个矩阵上很多,比如:
mapMatrix
答案 0 :(得分:5)
这不是monad应该做的。您可能对Data.Function
中定义的(&) :: a -> (a -> b)
感兴趣。
matrix ... & mapMatrix ... & mapMatrix .. & ...
请注意,bind的签名是
(>>=) :: m a -> (a -> m b) -> m b
并且不能简单地忽略m
s。
为了完整性,请注意,实际上可以使绑定的行为几乎与您希望它使用一个特定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
然后,以下工作也是如此:
runIdentity (matrix ... >>= mapMatrix ... >>= mapMatrix .. >>= ...)