I have a first typeclass which accepts lists of lists of lists of … of leaf
:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
class ListTree leaf t where
lmap :: (leaf -> leaf) -> t -> t
instance ListTree leaf leaf where lmap f v = f v
instance ListTree leaf t => ListTree leaf [t] where lmap f v = map (lmap f) v
I have a second typeclass which accepts 2-tuples and 3-tuples of a
:
class Tups a t where
tmap :: (a -> a) -> t -> t
instance Tups a (a,a) where tmap f (x,y) = (f x, f y)
instance Tups a (a,a,a) where tmap f (x,y,z) = (f x, f y, f z)
I would like to combine them to describe nested lists ending with 2- or 3-tuples of some leaf
type:
class LTTree leaf t where
ltmap :: (a -> a) -> t -> t
instance (Tups leaf x, ListTree x t) => LTTree leaf t where ltmap f v = lmap (tmap f) v
However, this last piece of code gives me several errors:
Could not deduce (LTTree leaf0 t)
from the context: LTTree leaf t
In the ambiguity check for ‘ltmap’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
Could not deduce (Tups leaf x0)
from the context: (Tups leaf x, ListTree x t)
In the ambiguity check for an instance declaration
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the instance declaration for ‘LTTree leaf t’
If I add AllowAmbiguousTypes
, I still get similar errors.
I can define the LTTree
class just fine by inlining the code of the other two typeclasses, though:
class LTTree leaf t where
ltmap :: (leaf -> leaf) -> t -> t
instance LTTree leaf (leaf,leaf) where ltmap f (x,y) = (f x, f y)
instance LTTree leaf (leaf,leaf,leaf) where ltmap f (x,y,z) = (f x, f y, f z)
instance LTTree leaf t => LTTree leaf [t] where ltmap f v = map (ltmap f)
How can I combine the ListTree leaf t
class with the Tups a t
class so that the leaves of the tree of lists are 2- or 3-tuples of a
? I don't mind adding extra GHC extensions if that can help.
If it matters, my real use case is to model trees of lists where the leaves are row-polymorphic record (using CTRex), where each field in the record is an instance of some typeclass (e.g. Show
, to print the trees).
data Nested a = Flat a | Nested (Nested [a])
– Benjamin Hodgson♦t
determineleaf
inLTTree
? Doesn'tt
determinea
inTups
? I think your classes need either fundeps or type families to express these dependencies. I'm not even sure you actually need the classes, though: what problem are you trying to solve? – chidata ConstrainedRec c where CRec :: Forall r c => Rec r -> ConstrainedRec c
(whereRec
andForall
are provided by CTrex). – user2407038data
approach is likely simpler and would work just as well. I'm new to Haskell so I'm not always sure what's the right tool for the job. It was interesting though to learn how to do the encoding as typeclasses. – Suzanne Soy