2013-07-11 15 views
8

Proszę mi pomóc zrozumieć następującą definicję:składnia newtype Haskell

newtype Writer w a = Writer { runWriter :: (a,w) } 

instance (Monoid w) => Monad (Writer w) where 
    return a    = Writer (a,mempty) 
    (Writer (a,w)) >>= f = let (a',w') = runWriter $ f a in Writer (a',w `mappend` w') 

Dlaczego runWriter jest zadeklarowana jako

runWriter :: (a,w) 

gdy jego rzeczywisty typ to:

runWriter :: Writer w a -> (a, w) 

Raz próbowałem z ghci zdałem sobie sprawę, że musi to być jakiś ukryty argument, ponieważ typ "a" musi zostać określony, ale co dokładnie się tutaj dzieje?

Odpowiedz

8

Ponieważ runWriter jest accessor pole rekord na Writer. To rzeczywiście prawie równoważne

runWriter (Writer x) = x 

Haskell ma tylko rekordy dać

  1. składni Więcej convient ponieważ ten rodzaj kodu akcesor jest dość powszechne
  2. Zdolność do aktualizacji funkcjonalnych
  3. kilku innych rozszerzenia

np.

someWriter{runWriter = (new, values)} -- Returns a new Writer. 

Jeśli to pomaga, pomyśl o tym, jako o "funkcjonalnym getterze" w najcięższym sensie. Może się to wydawać niezmiernie ważne w przypadku 1 pola, zawsze możesz dopasować wzorzec, ale gdy masz 5 pól, rekordy + aktualizacje funkcjonalne są bardzo pomocne. Zobacz LYAH, aby uzyskać bardziej szczegółowe wyjaśnienie.

0

Innym sposobem na to patrzeć: Można sobie wyobrazić określające 2-krotki jak tak (jeżeli specjalna składnia (,) nie były już specjalny wbudowane)

data (,) a b = (,) { fst :: a, snd :: b } 

a następnie fst i snd zachowaliby jak zwykle:

fst :: (a,b) -> a 
fst (x,y) = x 

(. newtype jak w przykładzie działa dla typów tylko z jednym polu wartości dla typów z wielu dziedzin, data jest potrzebne.)

Powiązane problemy