Si scopre che è sorprendentemente difficile utilizzare correttamente i tipi di tipo existential/rank-n nonostante l'idea molto semplice alla base.Necessità di wrapper di tipo esistenziale
Perché è necessario includere tipi esistenziali nei tipi data
?
Ho il seguente semplice esempio:
{-# LANGUAGE RankNTypes, ImpredicativeTypes, ExistentialQuantification #-}
module Main where
c :: Double
c = 3
-- Moving `forall` clause from here to the front of the type tuple does not help,
-- error is the same
lists :: [(Int, forall a. Show a => Int -> a)]
lists = [ (1, \x -> x)
, (2, \x -> show x)
, (3, \x -> c^x)
]
data HRF = forall a. Show a => HRF (Int -> a)
lists' :: [(Int, HRF)]
lists' = [ (1, HRF $ \x -> x)
, (2, HRF $ \x -> show x)
, (3, HRF $ \x -> c^x)
]
Se io commento la definizione di lists
, il codice viene compilato con successo. Se non lo commento, ricevo i seguenti errori:
test.hs:8:21:
Could not deduce (a ~ Int)
from the context (Show a)
bound by a type expected by the context: Show a => Int -> a
at test.hs:8:11-22
`a' is a rigid type variable bound by
a type expected by the context: Show a => Int -> a at test.hs:8:11
In the expression: x
In the expression: \ x -> x
In the expression: (1, \ x -> x)
test.hs:9:21:
Could not deduce (a ~ [Char])
from the context (Show a)
bound by a type expected by the context: Show a => Int -> a
at test.hs:9:11-27
`a' is a rigid type variable bound by
a type expected by the context: Show a => Int -> a at test.hs:9:11
In the return type of a call of `show'
In the expression: show x
In the expression: \ x -> show x
test.hs:10:21:
Could not deduce (a ~ Double)
from the context (Show a)
bound by a type expected by the context: Show a => Int -> a
at test.hs:10:11-24
`a' is a rigid type variable bound by
a type expected by the context: Show a => Int -> a at test.hs:10:11
In the first argument of `(^)', namely `c'
In the expression: c^x
In the expression: \ x -> c^x
Failed, modules loaded: none.
Perché sta succedendo? Non dovrebbe il secondo esempio essere equivalente al primo? Qual è la differenza tra questi usi di tipi n-rank? È possibile escludere una definizione ADT extra e usare solo tipi semplici quando voglio un tale tipo di polimorfismo?
Grazie mille per la spiegazione. Tutte le risposte sono state immensamente utili, ma penso che ho ricevuto "pezzi mancanti di puzzle" dalla tua risposta, quindi l'ho contrassegnato come accettato. –