使用>> =运算符时约束中的非类型变量参数

时间:2017-04-07 00:12:15

标签: haskell functional-programming monads

我有这个简单的代码:

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

1 个答案:

答案 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 .. >>= ...)