Re: [Haskell-cafe] Type Family Relations

Hi,
I think that
class HeaderOf addr hdr | addr -> hdr does not enforce that there must be a corresponding instance AddressOf hdr addr. Hence, the type checker cannot use that information either. Do you have a way to remedy that?
I've often wanted something similar, and experimenting with this the following two options seem to be equivalent and work as desired: ----------------------------------------------------------------------------- -- both options share this code: -- | The crucial assertion ipv4 :: AddrHdrPair IPv4 IPv4Header ipv4 = AddrHdrPair data IPv4Header = C1 data IPv4 = C2 data AppAddress = C3 data AppHeader = C4 ----------------------------------------------------------------------------- -- OPTION(1): -- type families + GADT with equality constraints type family HeaderOf addr type family AddressOf hdr data AddrHdrPair hdr addr where AddrHdrPair :: (hdr ~ HeaderOf addr ,addr ~ AddressOf hdr) => AddrHdrPair addr hdr type instance HeaderOf IPv4 = IPv4Header type instance AddressOf IPv4Header = IPv4 ----------------------------------------------------------------------------- -- OPTION(2): -- classes + GADT with instance constraints class HeaderOf addr hdr | addr -> hdr class AddressOf hdr addr | addr -> hdr data AddrHdrPair hdr addr where AddrHdrPair :: (HeaderOf addr hdr ,AddressOf hdr addr) => AddrHdrPair addr hdr instance AddressOf IPv4Header IPv4 instance HeaderOf IPv4 IPv4Header ----------------------------------------------------------------------------- -- And commenting out the above instances in turn -- to verify that everything indeed works, and to -- compare error message content: {- -- type instance HeaderOf IPv4 = IPv4Header Cafe0.hs:9:0: Couldn't match expected type `HeaderOf IPv4' against inferred type `IPv4Header' When generalising the type(s) for `ipv4' Failed, modules loaded: none. -- type instance AddressOf IPv4Header = IPv4 Cafe0.hs:9:0: Couldn't match expected type `AddressOf IPv4Header' against inferred type `IPv4' When generalising the type(s) for `ipv4' Failed, modules loaded: none. -} {- -- instance AddressOf IPv4Header IPv4 Cafe0.hs:9:7: No instance for (AddressOf IPv4Header IPv4) arising from a use of `AddrHdrPair' at Cafe0.hs:9:7-17 Possible fix: add an instance declaration for (AddressOf IPv4Header IPv4) In the expression: AddrHdrPair In the definition of `ipv4': ipv4 = AddrHdrPair Failed, modules loaded: none. -- instance HeaderOf IPv4 IPv4Header Cafe0.hs:9:7: No instance for (HeaderOf IPv4 IPv4Header) arising from a use of `AddrHdrPair' at Cafe0.hs:9:7-17 Possible fix: add an instance declaration for (HeaderOf IPv4 IPv4Header) In the expression: AddrHdrPair In the definition of `ipv4': ipv4 = AddrHdrPair Failed, modules loaded: none. -} -- endcode ----------------------------------------------------------------------------- I'm not sure if there are any circumstances under which these two don't behave equivalently. All the best, Matt

Generalizing the previous post, with: ----------------------------------------------------------------------------- {-# LANGUAGE GADTs #-} module Equ where data a:==:b where Equ :: (a ~ b) => a:==:b symm :: (a:==:a) symm = Equ refl :: (a:==:b) -> (b:==:a) refl Equ = Equ trans :: (a:==:b) -> (b:==:c) -> (a:==:c) trans Equ Equ = Equ cast :: (a:==:b) -> (a -> b) cast Equ = id ----------------------------------------------------------------------------- We can do (e.g.):
data IPv4Header = C1 data IPv4 = C2 type instance HeaderOf IPv4 = IPv4Header type instance AddressOf IPv4Header = IPv4
t0 :: IPv4 :==: AddressOf IPv4Header t0 = Equ t1 :: IPv4Header :==: HeaderOf IPv4 t1 = Equ t2 :: IPv4 :==: AddressOf (HeaderOf IPv4) t2 = Equ t3 :: IPv4Header :==: HeaderOf (AddressOf IPv4Header) t3 = Equ -- And interestingly `t6' shows that the type family option -- in the previous case is slightly stronger that the funcdeps -- option, ie the type fams one corresponds to the funcdeps -- addr -> hdr, hdr -> addr (instead of the weaker addr -> hdr). -- If this isn't desired I'd bet there's a way to modify the type -- instances to get the desired behavior. t5 :: AddrHdrPair a b -> a :==: AddressOf (HeaderOf a) t5 AddrHdrPair = Equ t6 :: AddrHdrPair a b -> b :==: HeaderOf (AddressOf b) t6 AddrHdrPair = Equ Matt
participants (1)
-
Matt Morrow