Haskell type classes and type families (cont'd)

Posted by Giuseppe Maggiore on Stack Overflow See other posts from Stack Overflow or by Giuseppe Maggiore
Published on 2010-04-08T07:17:46Z Indexed on 2010/04/08 7:23 UTC
Read the original article Hit count: 240

Filed under:

I need some help in figuring a compiler error which is really driving me nuts...

I have the following type class:

infixl 7 -->
class Selectable a s b where
  type Res a s b :: *
  (-->) :: (CNum n) => (Reference s a) -> (n,(a->b),(a->b->a)) -> Res a s b

which I instance twice. First time goes like a charm:

instance Selectable a s b where
  type Res a s b = Reference s b
  (-->) (Reference get set) (_,read,write) = 
        (Reference (\s -> 
                      let (v,s') = get s
                      in (read v,s'))
                   (\s -> \x ->
                      let (v,s') = get s
                          v' = write v x
                          (_,s'') = set s' v'
                      in (x,s'')))   

since the type checker infers

(-->) :: Reference s a -> (n,a->b,a->b->a) -> Reference s b

and this signature matches with the class signature for (-->) since

Res a s b = Reference s b

Now I add a second instance and everything breaks:

instance (Recursive a, Rec a ~ reca) => Selectable a s (Method reca b c) where
  type Res a s (Method reca b c) = b -> Reference s c
  (-->) (Reference get set) (_,read,write) =
    \(x :: b) -> 
        from_constant( Constant(\(s :: s)->
                          let (v,s') = get s :: (a,s)
                              m = read v
                              ry = m x :: Reference (reca) c
                              (y,v') = getter ry (cons v) :: (c,reca)
                              v'' = elim v'
                              (_,s'') = set s' v''
                              in (y,s''))) :: Reference s c

the compiler complains that

Couldn't match expected type `Res a s (Method reca b c)'
       against inferred type `b -> Reference s c'
The lambda expression `\ (x :: b) -> ...' has one argument,
which does not match its type
In the expression:
    \ (x :: b)
        -> from_constant (Constant (\ (s :: s) -> let ... in ...)) ::
             Reference s c
In the definition of `-->':
    --> (Reference get set) (_, read, write)
          = \ (x :: b)
                -> from_constant (Constant (\ (s :: s) -> ...)) :: Reference s c

reading carefully the compiler is telling me that it has inferred the type of (-->) thusly:

(-->) :: Reference s a -> (n,a->(Method reca b c),a->(Method reca b c)->a) -> (b -> Reference s c)

which is correct since

Res a s (Method reca b c) = b -> Reference s c

but why can't it match the two definitions?

Sorry for not offering a more succint and standalone example, but in this case I cannot figure how to do it...

© Stack Overflow or respective owner

Related posts about haskell