我开始使用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]
任何人都可以帮助我理解为什么我的模式与正确的类型不匹配吗?
答案 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]
。 x
和y
都是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