[Haskell-cafe] Type families and kind signatures

Louis Wasserman wasserman.louis at gmail.com
Thu Apr 2 19:18:40 EDT 2009


Mkay.  I get it now.  I was under the impression that, essentially, a data
family was precisely equivalent to a type family aliasing to a separately
declared datatype.

One more question: is there any way to get the low overhead of newtypes for
particular instances of a data family?  Is this impossible?  That is, is
there any way to do something like

data family Foo a
data instance Foo Int = Bar Int -- Bar is actually a newtype

Louis Wasserman
wasserman.louis at gmail.com


On Thu, Apr 2, 2009 at 12:47 PM, David Menendez <dave at zednenem.com> wrote:

> 2009/4/2 Louis Wasserman <wasserman.louis at gmail.com>:
> > Mkay.  One more quick thing -- the wiki demonstrates a place where the
> > original attempt worked, with a data family instead. (That is, replacing
> > 'type' with 'data' and adjusting the instance makes this program compile
> > immediately.)
> > a) Is there a type-hackery reason this is different from data families?
>
> It's not type hackery. Data families are different from type families,
> and the syntax for declaring instances of higher-kinded families is a
> consequence of those differences.
>
> An instance of a data family is a new type constructor, so you have to
> provide the additional arguments in order to declare the data
> constructors.
>
> data family Foo a :: * -> *
> data instance Foo Bool a = FB a a
> -- Foo Bool has kind * -> *, like [], so I could make it a Functor
>
> Instance of type families are always pre-existing type constructors.
>
> type family Bar a :: * -> *  -- Bar a must equal something of kind * -> *
> type instance Bar () = Maybe
>
> > b) Is there a reason this isn't made a lot clearer in the documentation?
> >  GHC's docs say that higher-order type families can be declared with kind
> > signatures, but never gives any examples -- which would make it a lot
> > clearer that the below program doesn't work.
>
> Here's a higher-kinded type family I've used.
>
> type family Sig t :: * -> *
>
> class (Traversable (Sig t)) => Recursive t where
>    roll :: Sig t t -> t
>    unroll :: t -> Sig t t
>
>
> The Traversable context wouldn't be valid if I had declared Sig t a ::
> *, because type families must always be fully applied.
>
>
> The difference is analogous to the difference between
>
> type M0 a = StateT Int IO a
> type M1   = StateT Int IO
>
> Since type synonyms (like type and data families) must always be fully
> applied, you can use M1 in places where you can't use M0, even though
> they're effectively the same thing.
>
> foo :: ErrorT String M1 a -- valid
> bar :: ErrorT String M0 a -- not valid
>
>
>
> --
> Dave Menendez <dave at zednenem.com>
> <http://www.eyrie.org/~zednenem/ <http://www.eyrie.org/%7Ezednenem/>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090402/478c7a42/attachment.htm


More information about the Haskell-Cafe mailing list