模式匹配Haskell列表

时间:2014-12-10 21:55:37

标签: haskell types

我开始使用the University of Pennsylvania's free online course materials学习Haskell。这些已故意上网,所以我认为我没有通过提出这个问题来帮助任何人做作业。

我从以下函数中得到了许多编译器错误,我用它来回答第一个作业的一部分,我无法弄清楚原因。我的职责是:

doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther [] = []
doubleEveryOther [x] = [x]
doubleEveryOther [x:y] = [x:(y*2)]
doubleEveryOther [x:y:ys] = [x:y*2:doubleEveryOther ys]

我得到的错误是:

01.hs:18:19:
    Couldn't match expected type ‘Integer’ with actual type ‘[a0]’
    In the pattern: x : y
    In the pattern: [x : y]
    In an equation for ‘doubleEveryOther’:
        doubleEveryOther [x : y] = [x : (y * 2)]

01.hs:18:27:
    Couldn't match expected type ‘Integer’ with actual type ‘[a0]’
    Relevant bindings include
      y :: [a0] (bound at 01.hs:18:21)
      x :: a0 (bound at 01.hs:18:19)
    In the expression: x : (y * 2)
    In the expression: [x : (y * 2)]
    In an equation for ‘doubleEveryOther’:
        doubleEveryOther [x : y] = [x : (y * 2)]

01.hs:19:19:
    Couldn't match expected type ‘Integer’ with actual type ‘[Integer]’
    In the pattern: x : y : ys
    In the pattern: [x : y : ys]
    In an equation for ‘doubleEveryOther’:
        doubleEveryOther [x : y : ys] = [x : y * 2 : doubleEveryOther ys]

01.hs:19:30:
    Couldn't match expected type ‘Integer’ with actual type ‘[Integer]’
    In the expression: x : y * 2 : doubleEveryOther ys
    In the expression: [x : y * 2 : doubleEveryOther ys]
    In an equation for ‘doubleEveryOther’:
        doubleEveryOther [x : y : ys] = [x : y * 2 : doubleEveryOther ys]

任何人都可以帮助我理解为什么我的模式与正确的类型不匹配吗?

3 个答案:

答案 0 :(得分:3)

问题很简单:[]表示元素列表。并且:表示加入元素和列表。所以[x:ys]实际上意味着[[x,y1,y2..]] - 请注意双括号。因此,它是您案例中Integer列表的列表,而不是Integer列表。

doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther [] = []
doubleEveryOther [x]= [x]
doubleEveryOther [x,y] = [x, y*2]
doubleEveryOther (x:y:ys) = x : y*2 : doubleEveryOther ys

如果您希望所有4个等式使用相同的语法,则不能使用[],因为它不允许ys,因此您必须在任何地方使用:

doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther [] = []
doubleEveryOther (x:[])= x:[]
doubleEveryOther (x:y:[]) = x : y*2 : []
doubleEveryOther (x:y:ys) = x : y*2 : doubleEveryOther ys

答案 1 :(得分:2)

代码应为:

doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther [] = []
doubleEveryOther [x] = [x]
doubleEveryOther (x:y:[]) = [x, (y*2)]
doubleEveryOther (x:y:ys) = x: y*2 : doubleEveryOther ys

您无法直接在列表上进行模式匹配,因为列表语法只是语法糖。您必须匹配函数调用(特别是调用(:),cons运算符)。这些匹配需要括在括号中。

并且您不会将cons调用括号括起来。 [1 : 2 : []][[1, 2]]相同。只是为了让它更清晰一点,在你的代码中你有[x : y*2]xy都是Int。但是,(:)属于(:) :: a -> [a] -> [a]类型。您使用两个Int来调用它,而不是Int[Int]

答案 2 :(得分:1)

此外,您的第3行是第4行的一部分,所以

doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther [] = []
doubleEveryOther [x]= [x]
doubleEveryOther (x:y:ys) = x : y*2 : doubleEveryOther ys