I'm working on an HList implementation and I'm stuck trying to implement a map
function for it. I've tried a lot of different approaches but with each one I reach compiler errors related to that function.
Following is an example of how I want to use a generic function Just
to apply it to all elements of the input data structure.
{-# 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
With this I'm getting the following compiler error:
No instance for (Apply (a0 -> Maybe a0) Int (Maybe Int))
arising from a use of `hMap'
The type variable `a0' is ambiguous
Is there at all a way to solve this and if not then why?
Just
with different concrete types on each successive application because your definition ofhMap
keeps reusing the samef
. The first time you apply it the type isInt -> Maybe Int
, the second time you apply it the type isChar -> Maybe Char
. However, I'm still not quite sure how to fix it. – Depressant| input output -> f
to theApply
class, the error messages will say that it is looking for instances, like(Bool -> Maybe Bool) Char (Maybe Char)
. I was thinking about usingcast
to disconnect the two usages off
on a type-level, but that just didn't feel very natural, and depending onTypeable
wasn't very alluring either. – Asclepiadean