Среди множества способов написать это можно двумя вариантами:
binListToDec xs = if length xs == 0 then 0 -- see below
else (head xs) + binListToDec (tail xs)
и
binListToDec [] = 0
binListToDec (x:xs) = x + binListToDec xs
Похоже, вы пытаетесь объединить биты каждого из них.Невозможно написать один шаблон, который соответствует одновременно 1) пустому списку и 2) непустому списку с 3) его голова и хвост сопоставляются отдельно.
xs
соответствует 1) и2). all@(x:xs)
соответствует 2) и 3) 1) и 3) не может быть сопоставлено , поскольку спаривание бессмысленно: пустоеСписок не имеет отдельной головы и хвоста.[]
и (x:xs)
совпадают списки из двух неперекрывающихся наборов возможных значений списка.
Обновление: существует ленивый образец совпадения all@(~(x:xs))
.Тильда предотвращает попытку совпадения (x:xs)
до тех пор, пока не возникнет необходимость оценить x
или xs
.Мы думаем о
binListToDec all@(~(x:xs)) = if length all == 0 then 0 else x + binListToDec
как эквивалентном
binListToDec all = if length all == 0
then 0
else let (x:xs) = all
in x + binListToDec
Ленивое сопоставление с образцом все еще может потерпеть неудачу, но здесь мы откладываем использование x
и xs
, пока не узнаем, что оно победило 't.
length binListToDec
пытается вычислить длину самой функции, а не длину ее аргумента, в вашей попытке.Правильный аргумент для length
используется выше.Кроме того, общепринятая сумма пустого списка равна 0, а не 1.