构建嵌套Monad

时间:2012-11-24 02:53:11

标签: haskell

我有两种自己的数据类型如下:

Block a = NoValue | Value a
data GraphAMT a = GraphAMT_ [[Block a]]

现在,我想为他们制作实例monad,如

instance Monad Block where
     return a = Value a
     NoValue >>= f = NoValue
     Value a >>= f = f a
     fail _ = NoValue

instance Monad GraphAMT where
     return a = GraphAMT_ [[Value a]]
     GraphAMT_ xs >>= f = ...?

我想知道GraphAMT是否可以成为monad?如果是,那么如何构建呢?

1 个答案:

答案 0 :(得分:3)

module MatrixOfMatrices where

将函数应用于矩阵的元素

data Block a = NoValue | Value a  deriving Show
data GraphAMT a = GraphAMT_ [[Block a]]  deriving Show

首先,你不需要Monad为每个元素添加三个,你需要fmap,所以你应该让你的类型成为Functor的一个实例,但最简单的做法是Block a仿函数第一:

instance Functor Block where
  fmap f NoValue  = NoValue
  fmap f (Value a) = Value (f a)

instance Functor GraphAMT where
 fmap f (GraphAMT_ xss) = GraphAMT_ . (map . map . fmap $ f) $ xss

何时

testData = GraphAMT_ [[NoValue,Value 2],[Value 56,Value 45,NoValue],[NoValue]]

然后

*MatrixOfMatrices> testData
GraphAMT_ [[NoValue,Value 2],[Value 56,Value 45,NoValue],[NoValue]]
*MatrixOfMatrices> fmap (*10) testData
GraphAMT_ [[NoValue,Value 20],[Value 560,Value 450,NoValue],[NoValue]]

正如你所希望的那样。

将矩阵制作成Monad

糟糕!我们需要定义(>>=) :: GraphAMT a -> (a -> GraphAMT b) -> GraphAMT b。它应该采用一个函数将元素转换为矩阵,按元素应用它,然后将得到的矩阵矩阵连接成一个矩阵。

问题在于没有明显的方法可以将矩阵矩阵制作成单个矩阵,就像列表列表成为列表一样。如果元素都是数字,我们可以将它们加在一起,形成一个最大尺寸的矩阵。我们不能使用这样的解决方案,因为Monad不能使用任何有关其元素的事实,因为它们必须适用于所有类型的元素。

没有明确的方法可以做到这一点 - 你可以通过加宽每一行以适应输入矩阵的值,或者使用转置将它们放在彼此之下,将它们放在一起。您可以根据每个人所处的基质矩阵中的位置开始重叠。