Domanda

Questa domanda è emersa durante la lettura del nuovo capitolo dell'eccellente Learn You a Haskell sui funzionari applicativi.

La tabella dei tipi Applicativa ha, come parte della definizione per l'istanza Maybe:

pure = Just

Se vado su GHCi e importare Control.Applicative, e faccio:

pure (3+)

Non capisco proprio niente (ha senso). Ma se lo uso in parte dell'espressione:

pure (3+) <*> Just 4

Ottengo solo 7. Suppongo che non sia sorprendente, ma mi manca qualcosa di integrale su come funzionano le macchine da scrivere, penso, che non ci sia ambiguità con la chiamata a pure qui.

Se la mia confusione ha senso, qualcuno può spiegare cosa sta succedendo in dettaglio?

È stato utile?

Soluzione

È solo un'inferenza di tipo. L'operatore (<*>) richiede che entrambi gli argomenti utilizzino la stessa Applicative istanza. Il lato destro è un Maybe, quindi anche il lato sinistro deve essere un :t expression. Quindi è così che scopre quale istanza viene utilizzata qui. Puoi guardare il tipo di qualsiasi espressione nell'interprete digitando <=> e forse se passi attraverso ogni sottoespressione e osserva il tipo inferito, otterrai una migliore immagine di ciò che sta succedendo.

Altri suggerimenti

Vale la pena guardare il tipo che il compilatore genera per pure (3+):

Prelude Control.Applicative> :t pure (3+)
pure (3+) :: (Num a, Applicative f) => f (a -> a)

Il tipo di questo termine è sovraccarico e la decisione sulla classe numerica e sulla classe applicativa è ritardata fino a dopo. Ma puoi forzare un tipo particolare con un'annotazione, ad esempio:

*Showfun Control.Applicative> pure (3+) :: Maybe (Double -> Double)
Just <function>

(Funziona perché Showfun ha una dichiarazione di istanza che stampa un valore di funzione come <function>.)

È solo una questione di quando il compilatore ha accumulato abbastanza informazioni per prendere una decisione.

Per espandere un po 'la risposta di newacct, se non ci sono abbastanza informazioni per inferire il tipo effettivo, il compilatore può (in alcuni casi) tentare di selezionare un tipo predefinito, limitato a quelli che soddisferebbero i vincoli di tipo in questione . In questo caso, il tipo inferito è IO (n - & Gt; n) per qualche istanza difficile da determinare di Num = & Gt; n. GHCi quindi lo valuta e getta via il valore restituito, senza effetti visibili.

Ecco un interessante thread SO sull'inferenza del tipo . Non specifico di Haskell, ma molti buoni collegamenti e cose da leggere sull'inferenza dei tipi nei linguaggi funzionali.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top