2014-12-10 4 views
2

Я начинаю изучать Haskell используя 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

Слишком устал за полный ответ, извините, но следующий может дать вам идею: '[X, Y]', '(х: у : YS) '. – Zeta

ответ

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 
+0

* '[x: ys]' означает фактически '[[x, y1, y2 ..]]' *. Это не на 100% точно.В шаблоне '[x: ys]', 'ys' может быть nil, и в этом случае нет' y1' и 'y2'. – Jubobs

+0

Хорошо спасибо, теперь я понимаю. –

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 s. Но минусы (:) имеет тип (:) :: a -> [a] -> [a]. Вы называете это двумя Int s, а не Int и [Int], как и вам.

+1

'[x]' является допустимым шаблоном для одноэлементного списка; он не должен быть '(x: [])'. Гарри понял это правильно. – Jubobs

+1

Не знал этого. Я отредактировал свой ответ. –

+0

Спасибо, что решает. Можете ли вы рассказать о том, почему работает ваш последний шаблон, но с помощью оператора cons в предпоследнем матче нет? Я хочу убедиться, что я действительно это понимаю. –

1

В кроме того, ваша третья линия является частью 4-й линии, так

doubleEveryOther :: [Integer] -> [Integer] 
doubleEveryOther [] = [] 
doubleEveryOther [x]= [x] 
doubleEveryOther (x:y:ys) = x : y*2 : doubleEveryOther ys 
Смежные вопросы