Is using UndecidableInstances okay? Alternatives?

I would like to do some magic in the library so that the type of product is polymorphically destroyed. This is a more or less working layout illustrating what I would like to do:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-} 
newtype Wrapped a = Wrapped { unwrap :: a } 

-- our example structure
ex :: (Int, (Int, Int))
ex = (1,(2,3))

class WrapDecomp x y | y -> x where
    decomp :: x -> y

instance (WrapDecomp x x', WrapDecomp y y')=> WrapDecomp (x,y) (x',y') where
    decomp (x,y) = (decomp x, decomp y)

instance WrapDecomp x (Wrapped x) where
    decomp = Wrapped


example = let w = decomp ex
              (w0, w1) = decomp ex
              (w0', (w1', w2')) = decomp ex :: (Wrapped Int, (Wrapped Int, Wrapped Int))
           in print $ ( unwrap w, unwrap w0, unwrap $ snd w1, unwrap $ fst w1 )
         -- Also works:
         -- in print $ ( unwrap w, unwrap w0, unwrap w1 )

My actual application is a library and will have two properties that make warts I noticed in the above:

  • Type constructor is Wrappednot exported

  • the user will always call unwrapfor all the Wrappeddata in the binding (due to the boring details of my application), so in practice there should be no ambiguity

The consensus seems to be that it is UndecidableInstancesnot very bad, but I would like to make sure that it is higher kosher before continuing.


Solution Update

, TypeFamilies :

{-# LANGUAGE TypeFamilies #-}
class Out a where
    type In a :: *
    decomp :: In a -> a

instance Out (Wrapped a) where
    type In (Wrapped a) = a
    decomp = Wrapped

instance (Out a, Out b)=> Out (a,b) where
    type In (a,b) = (In a,In b)
    decomp (x,y) = (decomp x, decomp y)
+5
1

UndecidableInstances , UndecidableInstances , , . , , .

, , , WrapDecomp x (x,y),

foo x = [fst $ decomp x, x]

fst decomp x (a,b) a b, instance WrapDecomp t (a,b), t x. , x a,

instance WrapDecomp a (a,b)

-

instance (Wrapdecomp x x', WrapDecomp y y') => WrapDecomp (x,y) (x',y')

, a = (x,y) x y, foo

WrapDecomp (x,y) ((x,y),b)

, ,

WrapDecomp y b

WrapDecomp x (x,y)

, .

+10

All Articles