Andy Gimblett | 13 Nov 21:26
Picon

A small (?) problem with type families

Hi all,

This email is literate Haskell.  I'm trying to use type families to
express some dependencies between type classes, and I'm running into
trouble, I think because I'm producing chains of dependencies which
the checker can't resolve...  Here's a minimised version of the state
I've got myself into.  :-)

 > {-# LANGUAGE FlexibleContexts #-}
 > {-# LANGUAGE TypeFamilies #-}

 > module Families where

First a type family where the type Y is functionally dependent on
the type X, and we have a function from Y to ().

 > class X a where
 >   type Y a
 >   enact :: Y a -> ()

Now another type family, where the type Q is functionally dependent
on the type P, _and_ it must also be an instance of the X
class.

 > class (X (Q s)) => P s where
 >   type Q s

(Perhaps there's a better way to express that dependency?)

Now a function which takes a value whose type is an instance of the Y
depending on the Q depending on the P.  (Phew!)  The function just
tries to call enact on that value.

 > bar :: P s => Y (Q s) -> ()
 > bar w = enact w

The error we get is:

src/Families.lhs:35:16:
     Couldn't match expected type `Y a' against inferred type `Y (Q s)'
     In the first argument of `enact', namely `w'
     In the expression: enact w
     In the definition of `bar': bar w = enact w

Presumably this way I'm chaining type dependencies is flawed.  Any
suggestions on how to improve it, and/or what to read to understand
what I'm dealing with better?  (So far I've read "Fun with type
functions V2", but that's about it, and I admit I didn't grok it all.)

Thanks!

-Andy
David Menendez | 13 Nov 21:36

Re: A small (?) problem with type families


On Fri, Nov 13, 2009 at 3:26 PM, Andy Gimblett <haskell <at> gimbo.org.uk> wrote: > First a type family where the type Y is functionally dependent on > the type X, and we have a function from Y to (). > >> class X a where >>   type Y a >>   enact :: Y a -> ()
This is ambiguous. Type families are not injective (that is, Y a ~ Y b does not imply a ~ b), so there's no way for the compiler to figure out which instance of X is being used when it encounters enact. Given these instances, instance X Int where type Y Int = Bool enact _ = () instance X Char where type Y Char = Bool enact _ = undefined What is "enact False"? I recall seeing a discussion of this in the GHC documentation, but I can't seem to locate it. -- -- Dave Menendez <dave <at> zednenem.com> <http://www.eyrie.org/~zednenem/>
Daniel Fischer | 13 Nov 22:00
Picon

Re: A small (?) problem with type families

Am Freitag 13 November 2009 21:36:59 schrieb David Menendez:

> On Fri, Nov 13, 2009 at 3:26 PM, Andy Gimblett <haskell <at> gimbo.org.uk> wrote: > > First a type family where the type Y is functionally dependent on > > the type X, and we have a function from Y to (). > > > >> class X a where > >>   type Y a > >>   enact :: Y a -> () > > This is ambiguous. Type families are not injective (that is, Y a ~ Y b > does not imply a ~ b), so there's no way for the compiler to figure > out which instance of X is being used when it encounters enact. > > Given these instances, > > instance X Int where > type Y Int = Bool > enact _ = () > > instance X Char where > type Y Char = Bool > enact _ = undefined > > What is "enact False"? > > I recall seeing a discussion of this in the GHC documentation, but I > can't seem to locate it.
Perhaps http://www.haskell.org/haskellwiki/GHC/Type_families#Frequently_asked_questions ?
David Menendez | 13 Nov 22:48

Re: A small (?) problem with type families

On Fri, Nov 13, 2009 at 4:00 PM, Daniel Fischer
<daniel.is.fischer <at> web.de> wrote:

> Am Freitag 13 November 2009 21:36:59 schrieb David Menendez: >> >> I recall seeing a discussion of this in the GHC documentation, but I >> can't seem to locate it. > > Perhaps http://www.haskell.org/haskellwiki/GHC/Type_families#Frequently_asked_questions ?
That's the one. I keep forgetting there's additional material on the wiki. -- -- Dave Menendez <dave <at> zednenem.com> <http://www.eyrie.org/~zednenem/>
Edward Kmett | 14 Nov 02:20
Picon
Gravatar

Re: A small (?) problem with type families

On Fri, Nov 13, 2009 at 3:36 PM, David Menendez <dave <at> zednenem.com> wrote:

On Fri, Nov 13, 2009 at 3:26 PM, Andy Gimblett <haskell <at> gimbo.org.uk> wrote:
> First a type family where the type Y is functionally dependent on
> the type X, and we have a function from Y to ().
>
>> class X a where
>>   type Y a
>>   enact :: Y a -> ()

This is ambiguous. Type families are not injective (that is, Y a ~ Y b
does not imply a ~ b), so there's no way for the compiler to figure
out which instance of X is being used when it encounters enact.

Note: that if you need this injectivity you can use a data family instead. 


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Andy Gimblett | 13 Nov 21:48
Picon

Re: A small (?) problem with type families

Ack. I've just realised that P/Q is not a functional dependency.  I  
need to use a multi-parameter type class there.  So my question is  
probably completely pointless - sorry!

Thanks anyway,

-Andy

On 13 Nov 2009, at 20:26, Andy Gimblett wrote:


> Hi all, > > This email is literate Haskell. I'm trying to use type families to > express some dependencies between type classes, and I'm running into > trouble, I think because I'm producing chains of dependencies which > the checker can't resolve... Here's a minimised version of the state > I've got myself into. :-) > > > {-# LANGUAGE FlexibleContexts #-} > > {-# LANGUAGE TypeFamilies #-} > > > module Families where > > First a type family where the type Y is functionally dependent on > the type X, and we have a function from Y to (). > > > class X a where > > type Y a > > enact :: Y a -> () > > Now another type family, where the type Q is functionally dependent > on the type P, _and_ it must also be an instance of the X > class. > > > class (X (Q s)) => P s where > > type Q s > > (Perhaps there's a better way to express that dependency?) > > Now a function which takes a value whose type is an instance of the Y > depending on the Q depending on the P. (Phew!) The function just > tries to call enact on that value. > > > bar :: P s => Y (Q s) -> () > > bar w = enact w > > The error we get is: > > src/Families.lhs:35:16: > Couldn't match expected type `Y a' against inferred type `Y (Q s)' > In the first argument of `enact', namely `w' > In the expression: enact w > In the definition of `bar': bar w = enact w > > Presumably this way I'm chaining type dependencies is flawed. Any > suggestions on how to improve it, and/or what to read to understand > what I'm dealing with better? (So far I've read "Fun with type > functions V2", but that's about it, and I admit I didn't grok it all.) > > Thanks! > > -Andy > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe <at> haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe
Andy Gimblett | 13 Nov 22:13
Picon

Re: A small (?) problem with type families

Hahaha, this is what I get for trying to think about Haskell on a  
Friday night.  Now I think it _is_ a functional dependency after all.   
Who knows how long it will be before I change my mind again? :-)

I shall think about this more carefully tomorrow...

Thanks again,

-Andy

On 13 Nov 2009, at 20:48, Andy Gimblett wrote:


> Ack. I've just realised that P/Q is not a functional dependency. I > need to use a multi-parameter type class there. So my question is > probably completely pointless - sorry! > > Thanks anyway, > > -Andy > > On 13 Nov 2009, at 20:26, Andy Gimblett wrote: > >> Hi all, >> >> This email is literate Haskell. I'm trying to use type families to >> express some dependencies between type classes, and I'm running into >> trouble, I think because I'm producing chains of dependencies which >> the checker can't resolve... Here's a minimised version of the state >> I've got myself into. :-) >> >> > {-# LANGUAGE FlexibleContexts #-} >> > {-# LANGUAGE TypeFamilies #-} >> >> > module Families where >> >> First a type family where the type Y is functionally dependent on >> the type X, and we have a function from Y to (). >> >> > class X a where >> > type Y a >> > enact :: Y a -> () >> >> Now another type family, where the type Q is functionally dependent >> on the type P, _and_ it must also be an instance of the X >> class. >> >> > class (X (Q s)) => P s where >> > type Q s >> >> (Perhaps there's a better way to express that dependency?) >> >> Now a function which takes a value whose type is an instance of the Y >> depending on the Q depending on the P. (Phew!) The function just >> tries to call enact on that value. >> >> > bar :: P s => Y (Q s) -> () >> > bar w = enact w >> >> The error we get is: >> >> src/Families.lhs:35:16: >> Couldn't match expected type `Y a' against inferred type `Y (Q s)' >> In the first argument of `enact', namely `w' >> In the expression: enact w >> In the definition of `bar': bar w = enact w >> >> Presumably this way I'm chaining type dependencies is flawed. Any >> suggestions on how to improve it, and/or what to read to understand >> what I'm dealing with better? (So far I've read "Fun with type >> functions V2", but that's about it, and I admit I didn't grok it >> all.) >> >> Thanks! >> >> -Andy >> >> _______________________________________________ >> Haskell-Cafe mailing list >> Haskell-Cafe <at> haskell.org >> http://www.haskell.org/mailman/listinfo/haskell-cafe > > _______________________________________________ > Haskell-Cafe mailing list > Haskell-Cafe <at> haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe

Gmane