Sto lavorando a un'implementazione di HList e sono bloccato cercando di implementare una funzione map
per questo. Ho provato un sacco di approcci diversi, ma con ognuno ho raggiunto errori del compilatore relativi a quella funzione.Mapping su una struttura di dati eterogenea con una funzione generica
Di seguito è riportato un esempio di come si desidera utilizzare una funzione generica Just
per applicarla a tutti gli elementi della struttura di dati di input.
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
-- | An input heterogenous data structure
recursivePairs :: (Int, (Char, (Bool,())))
recursivePairs = (1, ('a', (True,())))
-- | This is how I want to use it
recursivePairs' :: (Maybe Int, (Maybe Char, (Maybe Bool,())))
recursivePairs' = hMap Just recursivePairs
class HMap f input output where
hMap :: f -> input -> output
-- | A counterpart of a Nil pattern match for a list
instance HMap f()() where
hMap _ _ =()
-- | A counterpart of a Cons pattern match for a list
instance
(HMap f iTail oTail,
Apply f iHead oHead) =>
HMap f (iHead, iTail) (oHead, oTail)
where
hMap f (head, tail) = (apply f head, hMap f tail)
class Apply f input output where
apply :: f -> input -> output
instance Apply (input -> output) input output where
apply = id
Con questo sto ottenendo il seguente errore del compilatore:
No instance for (Apply (a0 -> Maybe a0) Int (Maybe Int))
arising from a use of `hMap'
The type variable `a0' is ambiguous
C'è affatto un modo per risolvere questo e se non allora perché?
credo che il problema è che il sistema di tipo non si rende conto che si sta un'istanza di 'Just' con diversi tipi di cemento su ogni successiva applicazione perché la tua definizione di' hMap' continua a riutilizzare lo stesso 'f'. La prima volta che lo applichi, il tipo è 'Int -> Maybe Int', la seconda volta che lo applichi il tipo è' Char -> Forse Char'. Tuttavia, non sono ancora abbastanza sicuro su come risolverlo. –
@GabrielGonzalez Sì, questo è esattamente il problema. E se aggiungi un fundep '| input output -> f' alla classe 'Apply', i messaggi di errore diranno che sta cercando istanze, come' (Bool -> Forse Bool) Char (Forse Char) '. Stavo pensando di usare ['cast'] (http: //hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Typeable.html # v: cast) per disconnettere i due usi di 'f' a livello di carattere, ma che non sembravano molto naturali, e a seconda di 'Typeable' non era molto allettante. –