2

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

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

现在,我想为他们制作实例单子,比如

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 是否可以是单子?如果是,那么如何构建它?

4

1 回答 1

3
module MatrixOfMatrices where

将函数应用于矩阵的元素

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

首先,你不需要 Monad 为每个元素添加三个,你需要fmap,所以你应该让你的类型成为 Functor 的实例,但首先创建Block一个 functor 是最简单的:

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 无法使用有关其元素的任何事实,因为它们必须适用于所有类型的元素。

没有明确的方法可以做到这一点 - 您可以通过加宽每一行以容纳传入矩阵的值将它们彼此相邻,或者使用转置将它们放在彼此下方。您可以根据每个矩阵在矩阵中的位置开始重叠。

于 2012-11-26T02:37:55.197 回答