[Haskell-cafe] Am I using type families well?

Yves Parès limestrael at gmail.com
Tue Nov 2 03:32:52 EDT 2010


I understand your point Ryan, but in that case, why didn't the error occur
when Resource and ResourceId were separated classes?

BTW, I assume for your Int instance of Resource, you meant:
> instance Resource Int where
>   type IdOf *Int* = Int
>   type LocOf *Int* = String
>   type CfgOf *Int* = ()
>   retrieveLoc () n = "Int_ " ++ show n
>   load = undefined
>   unload = undefined


2010/11/2 Ryan Ingram <ryani.spam at gmail.com>

> This one is easy:
>
> > -- | Class describing a resource of type @rsc@
> > class (Ord (IdOf rsc)) => Resource rsc where
> >   type IdOf rsc
> >   type LocOf rsc
> >   type CfgOf rsc
> >   retrieveLoc :: CfgOf rsc -> IdOf rsc -> LocOf rsc
> >   load   :: LocOf rsc -> IO (Maybe rsc)
> >     -- ^ Called when a resource needs to be loaded
> >   unload :: rsc -> IO ()
> >     -- ^ Idem for unloading
>
> Consider this:
>
> instance Resource () where
>   type IdOf () = Int
>   type LocOf () = String
>   type CfgOf () = ()
>   retrieveLoc () n = "Unit_" ++ show n
>   load = undefined
>   unload = undefined
>
> instance Resource Int where
>   type IdOf () = Int
>   type LocOf () = String
>   type CfgOf () = ()
>   retrieveLoc () n = "Int_ " ++ show n
>   load = undefined
>   unload = undefined
>
> foo = retrieveLoc :: () -> Int -> String  -- which retrieveLoc is called
> here?
>
> The problem, in case you haven't surmised it, is that retrieveLoc is
> ambiguous; you can never call it!  There's no way to know which
> instance you might be referring to.  You can work around it by making
> one of the type families into a data family (which is injective; you
> know that if CfgOf x = CfgOf y, then x = y).  Or you can add a proxy
> parameter to retrieveLoc:
>
> > data Proxy a = Proxy
> > retrieveLoc :: Proxy rsc -> CfgOf rsc -> IdOf rsc -> LocOf rsc
>
> now:
>
> > foo = retrieveLoc (Proxy :: Proxy ())
>
> and ghc can correctly infer foo's type as
> > foo :: () -> Int -> String
>
> and foo will call the retrieveLoc from the () instance.
>
>  -- ryan
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20101102/7adf897c/attachment.html


More information about the Haskell-Cafe mailing list