[Haskell-cafe] Re: Type error

oleg at pobox.com oleg at pobox.com
Sun Apr 8 19:54:52 EDT 2007

Alfonso Acosta wrote:

I have a type problem in my code which I dont know how to solve

> data HDSignal a = HDSignal
> class HDPrimType a where
> class PortIndex a where
> class SourcePort s where
>  -- Plug an external signal to the port
>  plugSig  :: (HDPrimType a, PortIndex ix) =>ix -> s  ->(HDSignal a -> b) -> b
> class DestPort d where
>  -- Supply a signal to the port
>  supplySig  :: (PortIndex ix, HDPrimType a) => HDSignal a -> ix -> d -> d
> -- Connect providing indexes
> connectIx :: (SourcePort s, PortIndex six, DestPort d, PortIndex dix) =>
>              six -> s -> dix -> d -> d
> connectIx six s dix d = plugSig six s $ (push2 supplySig) dix d

I'm afraid the example may be a bit too simplified. The first
question: what is the role of the |HDPrimType a| constraint in plugSig
and supplySig? Do the implementations of those functions invoke some
methods of the class HDPrimType? Or the |HDPrimType a| constraint is
just to declare that the parameter |a| of HDSignal is a member of
HDPrimType? If it is the latter, that intention is better declared

> data HDPrimType a => HDSignal a = HDSignal

Any function constructing the value HDSignal has to prove to the
typechecker that the type |a| satisfied the HDPrimType
constraint. Once we ensured that only properly constrained HDSignal
can be constructed, the HDPrimType constraint can be removed from the
signature of plugSig and supplySig, and the example compiles. It
compiles because plugSig requires a supplicant that can process any
HDSignal, and supplySig promises to be exactly this supplicant, which
is able to process HDSignal without looking at it. With the original
HDPrimType constraint, the meaning is the same. Although neither
plugSig or supplySig care about which particular instance of
HDPrimType is chosen, the typechecker must chose some instance. Alas,
there is no information in the signature of connectIx to help the
typechecker chose the instance. There is no defaulting.

If plugSig and supplySig do use the methods of HDPrimType, one could
use existentials:
> data HDSignal' = forall a. HDPrimType a => HDSignal' (HDSignal a)
> class SourcePort s where
> plugSig  :: (PortIndex ix) => ix -> s  -> (HDSignal' -> b) -> b

> class DestPort d where
> supplySig  :: (PortIndex ix) => HDSignal' -> ix -> d -> d

That works too.

More information about the Haskell-Cafe mailing list