2015-04-30 8 views
5

Próbowałem rozwiązać problemy Haskella 99 i moja pierwsza próba była właśnie taka. Chociaż rozwiązanie może być trochę niepoprawne, po prostu chcę wiedzieć, dlaczego Haskell rzuca ostrzeżenie na pierwszą i daje błędny wynikczy Haskell jest wrażliwy na porządek w definicji funkcji?

> let { mylast (x:xs) = mylast xs; mylast [] = 0 ;mylast [x] = x;} 
Pattern match(es) are overlapped 

> mylast [1,2,3,58,8,6,1,231,10] 
> 0 

, ale poniższy kod działa poprawnie.

> let { mylast [] = 0 ;mylast [x] = x;mylast (x:xs) = mylast xs;} 
> mylast [1,2,3,58,8,6,1,231,10] 
> 10 
+0

BTW, zwracanie "0" jako "domyślne niepowodzenia" jest bardzo nie-Haskelowe. Powinieneś prawdopodobnie zrobić to: 'myLast :: [a] -> Maybe a'; 'myLast [] = Nic"; 'myLast [x] = Po prostu x'. – leftaroundabout

+0

Po prostu uczę się Haskella i nie wiedziałem, jak zwrócić zero. Właśnie zacząłem patrzeć na może typ – Ramkumar

Odpowiedz

11

Tak, wzory w definicji funkcji są wypróbowywane w określonej kolejności i (tylko) używana jest pierwsza pasująca linia.

Tak w definicji

mylast (x:xs) = mylast xs 
mylast [] = 0 
mylast [x] = x 

(sformatowany dla jasności), non-empty-lista zawsze będzie obsługiwane przez pierwszą linię, a nawet listy [x] (z x=x i xs=[]). Tak więc twoje obliczenia mylast z przyjemnością zignorują element co każdy element na liście, a na koniec spojrzą na [], zwracając 0.

7

... innymi słowy, Haskell nie bierze pod uwagę, które z dwóch dopasowań jest bardziej ogólne, a następnie używa bardziej konkretnego. Po prostu uważa, że ​​“ pasuje czy nie? ”

W niektórych przypadkach nie można powiedzieć, który z dwóch dopasowań jest bardziej szczegółowy. Na przykład,

foo :: Int -> Int -> Int 
foo 0 _ = 0 
foo _ 1 = 1 
foo n m = foo (m-1) n 

Jeśli Haskell miał wybrać najbardziej pasujący konkretny wzór, to co wynik foo 0 1 powinna przynieść?

Musisz mieć dowolny arbitralny rozłącznik do takich funkcji, aw Haskell, który jest po prostu zamówieniem: zawsze pasuje do górnej klauzuli najpierw.

Powiązane problemy