stavo sperimentando con le famiglie di tipo ieri e sono imbattuto in un ostacolo con il seguente codice:Scrivendo Un polimorfico Funzione in una famiglia tipo
{-# LANGUAGE TypeFamilies #-}
class C a where
type A a
myLength :: A a -> Int
instance C String where
type A String = [String]
myLength = length
instance C Int where
type A Int = [Int]
myLength = length
main = let a1 = [1,2,3]
a2 = ["hello","world"]
in print (myLength a1)
>> print (myLength a2)
Qui ho un tipo associato di classe C e una funzione che calcola la lunghezza del tipo associato. Tuttavia, il codice di cui sopra mi dà questo errore:
/tmp/type-families.hs:18:30:
Couldn't match type `A a1' with `[a]'
In the first argument of `myLength', namely `a1'
In the first argument of `print', namely `(myLength a1)'
In the first argument of `(>>)', namely `print (myLength a1)'
/tmp/type-families.hs:19:30:
Couldn't match type `A a2' with `[[Char]]'
In the first argument of `myLength', namely `a2'
In the first argument of `print', namely `(myLength a2)'
In the second argument of `(>>)', namely `print (myLength a2)'
Failed, modules loaded: none.
Se, tuttavia cambio "tipo" a "dati" il codice compila e funziona:
{-# LANGUAGE TypeFamilies #-}
class C a where
data A a
myLength :: A a -> Int
instance C String where
data A String = S [String]
myLength (S a) = length a
instance C Int where
data A Int = I [Int]
myLength (I a) = length a
main = let a1 = I [1,2,3]
a2 = S ["hello","world"]
in
print (myLength a1) >>
print (myLength a2)
Perché la "lunghezza" non funzionare come previsto nel primo caso? Le righe "tipo A String ..." e "tipo A Int ..." specificano che il tipo "A a" è un elenco, quindi myLength dovrebbe avere rispettivamente i seguenti tipi: "myLength :: [String] -> Int" o "myLength :: [Int] -> Int".
Sembra che potrebbe essere necessario un '{- # LANGUAGE TypeSynonymInstances - #}' anche lì, poiché 'String' è un sinonimo di tipo per' [Char] ', e senza il flag GHC si aspetta che vengano create le teste di istanza di variabili di tipo primitive. – Raeez