我试着去理解单子,我做了一个练习题:对于这个问题,我做了两件事,一个函数和一个整数,然后我处理它在下面的方式:我取int提供的值,然后像这样拆分整数:
3 -> (2,1) (1,2)
4 -> (3,1) (2,2) (1,3)
so on.
其工作原理和实现方式如下:
numberSplit :: Int -> [(Int,Int)]
numberSplit 0 = []
numberSplit 1 = []
numberSplit n = numberSplitHelper 1 (n - 1)
--Helper functions --
numberSplitHelper :: Int -> Int -> [(Int, Int)]
numberSplitHelper 0 0 = []
numberSplitHelper 0 1 = []
numberSplitHelper 1 0 = []
numberSplitHelper 1 1 = [(1, 1)]
numberSplitHelper n 1 = [(n, 1)]
numberSplitHelper n m = (n, m) : numberSplitHelper (n + 1) (m - 1)
接下来,我将递归地对numberSplit函数返回的列表中的每一个值应用该函数,并且我尝试用单子来做这件事,作为单子的练习。例如,如果我输入:
(sort
(andExpressionsAtSize
(\ i -> if i == 1 then
[EBase True,EBase False]
else if i == 2 then
[ENot (EBase True),ENot (EBase False)]
else [])
3))
我的预期输出为:
[EAnd (EBase False,EBase False)
,EAnd (EBase False,EBase True)
,EAnd (EBase True,EBase False)
,EAnd (EBase True, EBase True)]
我尝试执行以下操作:
andExpressionsAtSize :: (Int -> [Expression]) -> Int -> [Expression]
andExpressionsAtSize f 0 = []
andExpressionsAtSize f n = do
intList <- numberSplit n
intList >>= f
它给出了以下错误:
Couldn't match type ‘(,) Int’ with ‘[]’
Expected: [Expression]
Actual: (Int, Expression)
根据我对单子的理解,它做了以下几点:
1. It takes in a list.
2. Applies the function on the left hand side to the list recursively.
所以它会将f应用到头部一直到尾部。基于这个理解
intList >>= f
应该返回一个类型的[Expression],但它没有,这让我很困惑,有人能澄清一下发生了什么吗?
编辑:有些人指出我从来没有使用过EAnd,我忘了提到在输出中每个元素都应该用EAnd连接。
1条答案
按热度按时间6kkfgxo01#
intList
并不是一个列表,正如它的名字所暗示的那样!如果
y
是一个列表,那么x
将是标记为here
的延续部分中列表的 * 元素 * 之一。因为
numberSplit n
是一个列表,所以intList
将是该列表的成员--即类型为(Int, Int)
的一对。(我相信这是您的核心困惑,一旦纠正,您将有一些想法的事情,试图修复您的代码的其余部分;但如果这种看法是错误,请指出我哪里做错了,我会尽力提供进一步的帮助。)