"A lazy (~) pattern cannot bind existential type variables"?

Conal Elliott conal at conal.net
Sun Nov 16 01:33:40 EST 2008


What is the reasoning behind the ghc restriction that "A lazy (~) pattern
cannot bind existential type variables"?

This error came up for me in the following code:

    -- | Add a continuation.
    data WithCont h b c = forall a. WC (h b a) (a -> c)

    instance Functor (WithCont h b) where
      fmap g ~(WC f k) = WC f (fmap g k)

The error message:

    A lazy (~) pattern cannot bind existential type variables
      `a' is a rigid type variable bound by
          the constructor `WC' at Data/Zip/FoldL.hs:66:11
    In the pattern: ~(WC f k)

I also tried this variation:

    instance Functor (WithCont h b) where
      fmap g wc = WC f (fmap g k)
        where WC f k = wc

and got this message:

    My brain just exploded.
    I can't handle pattern bindings for existentially-quantified
constructors.
    Instead, use a case-expression, or do-notation, to unpack the
constructor.
    In the binding group for
        WC f k
    In a pattern binding: WC f k = wc

I can work around these limitations by using a lambda:

    instance Functor (WithCont h b) where
      fmap g = \ (WC f k) -> WC f (fmap g k)

which I believe is equivalent.  Please correct me if I'm wrong here.

For infix definitions like (<*>), however, this work-around is less
pleasant.
For instance,

    (<*>) = \ (WC hf hk) (WC xf xk) ->
      WC (hf `zip` xf) (\ (a,a') -> (hk a) (xk a'))

instead of the prettier but forbidden

    ~(WC hf hk) <*> ~(WC xf xk) =
      WC (hf `zip` xf) (\ (a,a') -> (hk a) (xk a'))


If you're curious what these definitions are about, see
http://conal.net/blog/posts/enhancing-a-zip/ .

Thanks,   - Conal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/glasgow-haskell-users/attachments/20081115/d65c53af/attachment-0001.htm


More information about the Glasgow-haskell-users mailing list