2014-12-08 3 views
4

У меня есть код, который работает отлично:Несоответствия типа с шаблоном

let rec calculate s l acc = 
    if length s = 0 then 
     acc 
    else 
     if first s = l then 
      calculate (rest s) l (acc+1) 
     else 
      calculate (rest s) (first s) acc 

Я хочу переписать его с помощью сопоставления с образцом:

let rec calculate s l acc = 
    function 
    | _, _, _ when length s = 0 -> acc 
    | _, _, _ when first s = l -> calculate (rest s) l (acc+1) 
    | _, _, _     -> calculate (rest s) (first s) acc 

Но последняя функция возвращает сообщение об ошибке:

| _, _, _ when first s = l -> calculate (rest s) l (acc+1) -----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

/Пользователи/demas/tempor/stdin (512,36): ошибка FS0001: Несоответствие типов. Ожидающий 'a, но заданный ' b * 'c *' d -> 'a Получаемый тип будет бесконечным при объединении' 'a' и '' b * 'c *' d -> 'a'

Почему?

+0

Это случай, когда сопоставление образцов на самом деле ничего не приносит. Я бы просто использовал ваш исходный код с 'elif' вместо' else if', чтобы избежать слишком глубокого отступа, но все. – Tarmil

ответ

6

Ключевое слово function подразумевает, что последний (неявный) параметр функции calculate должен быть кортеж, содержащий 3 элемента, потому что вы соответствия на _, _, _ Вы можете переписать его как:

let rec calculate s l acc = 
    match s, l, acc with 
    | _, _, _ when length s = 0 -> acc 
    | _, _, _ when first s = l -> calculate (rest s) l (acc+1) 
    | _, _, _     -> calculate (rest s) (first s) acc 

Также вас мог бы сделать совпадение рисунков более ясным, переписывая его так:

let rec calculate s l acc = 
    match (length s), (first s = l) with 
    | 0, _ -> acc 
    | _, true -> calculate (rest s) l (acc+1) 
    | _, _ -> calculate (rest s) (first s) acc 
+0

Спасибо. Но почему он повторяет эту правильную строку «когда первый s = l -> вычисляет (rest s) l (acc + 1)», а не предыдущий в сообщении об ошибке? – demas

+1

Это потому, что все ветви соответствия шаблонов должны быть одного типа. Компилятор предположил, что этот тип должен быть «a (общий тип параметра« acc ») - тип первой ветви, потому что вывод типа происходит сверху вниз. И именно поэтому он дает ошибку типа во второй ветви. – Petr

+1

Также я добавил код соответствия шаблону, который короче и имел бы больше смысла. – Petr