I have the following code, which I use to convert a HList-of-touples (or more like, tree-of -touples) into the same shape, but instead of a tuple, just keeping the second element.
The problem is, this needs UndecidableInstances
(see the error message in comment). Is it possible to make the type system aware that indeed, a :. c
determines b :. d
so the error (and the need for UndecidableInstances) to go away?
class TupSnd a b | a -> b where
tupSnd :: a -> b
instance TupSnd PGTup (Only Action) where
tupSnd a = Only (snd a)
-- This needs UndecidableInstances allegedly, but probably there's some type-level trick to make it work?
--
-- Error:
--
-- Reason: lhs type ‘a :. c’ does not determine rhs type ‘b :. d’
--
-- Which sounds like it shouldn't be the case logically.
instance (TupSnd a b, TupSnd c d) => TupSnd (a :. c) (b :. d) where
tupSnd (a :. c) = tupSnd a :. tupSnd c
For context, :.
is the glorified tuple constructor helper from postgresql-simple
, and I also have
type PGTup = (Identifier, Action)
type PGTup2 = PGTup :. PGTup
type PGTup2_2 = PGTup2 :. PGTup2
type PGTup3 = PGTup :. PGTup2
type PGTup4 = PGTup :. PGTup3
You can enable UndecidableInstances
, it's a harmless extension.
Or, alternatively, you could switch to type families. The following code compiles (with no other extension beyond TypeFamilies
). In the code below, I slightly changed your types so to avoid importing a bunch of modules. You should be able to easily adapt it back to your case.
{-# LANGUAGE TypeFamilies #-}
class TupSnd a where
type T a
tupSnd :: a -> T a
instance TupSnd Bool where
type T Bool = String
tupSnd a = show a
instance (TupSnd a, TupSnd c) => TupSnd (a, c) where
type T (a, c) = (T a, T c)
tupSnd (a, c) = (tupSnd a, tupSnd c)
Personally, I find type families simpler to use than functional dependencies, so I prefer to use them whenever possible.