2015-06-18 9 views
12

Perché f <$> g <$> x equivale a (f . g) <$> x sebbene <$> non sia associato al diritto?

(Questo tipo di equivalenza è valido in a popular idiom con piano $, ma attualmente $ è giusto-associativa!)

<*> ha la stessa associatività e precedenza come <$>, ma si comporta in modo diverso!

Esempio:

Prelude Control.Applicative> (show . show) <$> Just 3 
Just "\"3\"" 
Prelude Control.Applicative> show <$> show <$> Just 3 
Just "\"3\"" 
Prelude Control.Applicative> pure show <*> pure show <*> Just 3 

<interactive>:12:6: 
    Couldn't match type `[Char]' with `a0 -> b0' 
    Expected type: (a1 -> String) -> a0 -> b0 
     Actual type: (a1 -> String) -> String 
    In the first argument of `pure', namely `show' 
    In the first argument of `(<*>)', namely `pure show' 
    In the first argument of `(<*>)', namely `pure show <*> pure show' 
Prelude Control.Applicative> 
Prelude Control.Applicative> :i (<$>) 
(<$>) :: Functor f => (a -> b) -> f a -> f b 
    -- Defined in `Data.Functor' 
infixl 4 <$> 
Prelude Control.Applicative> :i (<*>) 
class Functor f => Applicative f where 
    ... 
    (<*>) :: f (a -> b) -> f a -> f b 
    ... 
    -- Defined in `Control.Applicative' 
infixl 4 <*> 
Prelude Control.Applicative> 

Dalla definizione di <$>, mi sarei aspettato show <$> show <$> Just 3 a fallire, anche.

risposta

21

Perché f <$> g <$> x equivale a (f . g) <$> x?

Questo non è tanto un farsetto che una cosa di Haskell. La ragione per cui funziona è che le funzioni sono funzioni. Entrambi gli operatori <$> lavorano in diversi funtori!

f <$> g è infatti stesso come f . g, quindi l'equivalenza che stai chiedendo circa è un po 'più banale che f <$> (g <$> x) ≡ f . g <$> x.

+1

Grazie per questa intelligente osservazione! –

+5

Beh, l'hai osservato tu, vero? Ho appena analizzato e digitato il testo ... – leftaroundabout

+0

Bene, intendevo dire prendere in considerazione l'altra istanza di Functor. Forse, "osservazione" non è una buona parola per questo. –

Problemi correlati