Haskell中单子的奇怪行为

mi7gmzs6  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(183)

我试着去理解单子,我做了一个练习题:对于这个问题,我做了两件事,一个函数和一个整数,然后我处理它在下面的方式:我取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连接。

6kkfgxo0

6kkfgxo01#

intList并不是一个列表,正如它的名字所暗示的那样!

do
    {- ... -}
    x <- y
    {- here -}

如果y是一个列表,那么x将是标记为here的延续部分中列表的 * 元素 * 之一。

do
    intList <- numberSplit n
    {- ... -}

因为numberSplit n是一个列表,所以intList将是该列表的成员--即类型为(Int, Int)的一对。
(我相信这是您的核心困惑,一旦纠正,您将有一些想法的事情,试图修复您的代码的其余部分;但如果这种看法是错误,请指出我哪里做错了,我会尽力提供进一步的帮助。)

相关问题