2011-08-19 14 views
12

Aby pomóc mi w nauce Funkcjonalnych Funktorów i Funktorów, pomyślałem, że dobrze byłoby zobaczyć, w jaki sposób Either jest zaimplementowany z typami Functor i Applicative. Oczywiście mogłem po prostu iść dalej i czytać kod, ale uważam, że bardziej przydatne jest samodzielne wprowadzanie w życie, aby lepiej zrozumieć rzeczy.Próbuję zaimplementować Data.Either

FYI próbuję wdrożyć wersję Haskell o wynikach tej prezentacji http://applicative-errors-scala.googlecode.com/svn/artifacts/0.6/chunk-html/index.html

W każdym razie, to co mam tak daleko

data Validation a b = Success a | Failure b deriving (Show, Eq) 

instance Functor (Validation a) where 
    fmap f (Failure x) = Failure x 
    fmap f (Success x) = Success (f x) 

Ale gdy próbuję uruchomić to z ghci Właśnie pojawia się następujący komunikat o błędzie: -

[1 of 1] Compiling Main    (t.hs, interpreted) 

t.hs:5:35: 
    Couldn't match type `b' with `a1' 
     `b' is a rigid type variable bound by 
      the type signature for 
      fmap :: (a1 -> b) -> Validation a a1 -> Validation a b 
      at t.hs:4:5 
     `a1' is a rigid type variable bound by 
      the type signature for 
      fmap :: (a1 -> b) -> Validation a a1 -> Validation a b 
      at t.hs:4:5 
    Expected type: a 
     Actual type: b 
    In the return type of a call of `f' 
    In the first argument of `Success', namely `(f x)' 
    In the expression: Success (f x) 

t.hs:5:37: 
    Couldn't match type `a' with `a1' 
     `a' is a rigid type variable bound by 
      the instance declaration at t.hs:3:30 
     `a1' is a rigid type variable bound by 
      the type signature for 
      fmap :: (a1 -> b) -> Validation a a1 -> Validation a b 
      at t.hs:4:5 
    In the first argument of `f', namely `x' 
    In the first argument of `Success', namely `(f x)' 
    In the expression: Success 

Nie jestem do końca pewien, dlaczego tak jest, czy ktoś może pomóc?

Odpowiedz

13

Starasz się uczynić pracę Functor instancji na Success części, która jest normalną rzeczą do zrobienia, ale ze względu na kolejność swoich parametrów typu jest on zdefiniowany od typu w Failure części zamiast.

Skoro już zdefiniowany jako

data Validation a b = Success a | Failure b 

instance Functor (Validation a) where 
    ... 

Oznacza to, że realizacja fmap powinna mieć typ (x -> y) -> Validation a x -> Validation a y. Ale ponieważ druga zmienna typu jest dla przypadku Failure, to nie sprawdza typu.

Chcesz zmienna typu dla przypadku Success być ostatni zamiast:

data Validation b a = Success a | Failure b 
+0

Ahhh widzę, dzięki, jestem zakładając 'walidacji danych a b = Niepowodzenie a | Sukces b ("Show, Eq)" również byłby poprawny. Dzięki! – djhworld

+1

@djworld: Tak. To samo dotyczy nazw zmiennych typu i kolejności zamienionych konstruktorów. – hammar

+5

@djhworld: A teraz rozumiesz również, dlaczego w 'Albo b',' Left' reprezentuje przypadek awarii (nie tylko dlatego, że nie jest to "właściwy" wynik). –