Eric M. Pashman | 19 Jan 00:32 2013
Picon

Updating/understanding code from implicit configurations paper

Reading the implicit configurations paper (Kiselyov & Shan), I couldn't figure out how this bit of code (section 3.2) was meant to work:

    class Modular s a | s -> a where modulus :: s -> a

    normalize :: (Modular s a, Integral a) => a -> M s a
    normalize a :: M s a = M (mod a (modulus (undefined :: s)))

Here, `M` is just a type representing a modulus, with a phantom parameter that's going to make the magic happen:

    data M s a = M a deriving (Eq, Show)

Running this in GHC 7.4.2, with the extensions for scope typed variables, multi parameter type classes, and functional dependencies enabled, I get a parse error on the type signature on the LHS of the definition of `normalize`. Having moved the deprecated LHS result annotation to the RHS, I think this should be equivalent:

    normalize :: (Modular s a, Integral a) => a -> M s a
    normalize x = (M (mod x (modulus (undefined :: s)))) :: M s a

But indeed this won't type-check. I've tried annotating the argument (x :: a) and the result of `modulus` (modulus (undefined :: s) :: a), as well as various other terms, but GHC always tells me the phantom type is ambiguous or the type of the argument of `normalize` can't be unified with the parameter `a` in the result type.

Now, like I said, I didn't see how this could work in the first place, so I'm at a loss as to what the problem is. Can someone show me how to get this to compile with a recent version of GHC? I'd also appreciate any insight into what `normalize` is meant to do, if the working code turns out to differ in just a type annotation or two. ...

Regards,

Eric

PS: The literate Haskell version of the paper is here.
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Shachaf Ben-Kiki | 19 Jan 00:54 2013
Picon

Re: Updating/understanding code from implicit configurations paper

On Fri, Jan 18, 2013 at 3:32 PM, Eric M. Pashman <eric.pashman <at> gmail.com> wrote:
>
>     normalize :: (Modular s a, Integral a) => a -> M s a
>     normalize x = (M (mod x (modulus (undefined :: s)))) :: M s a
>

If you want your type variables to be scoped, you have to annotate
them explicitly:

  normalize :: forall s a. (Modular s a, Integral a) => a -> M s a
  normalize x = M (mod x (modulus (undefined :: s)))

See <http://www.haskell.org/ghc/docs/7.4.2/html/users_guide/other-type-extensions.html#scoped-type-variables>.

    Shachaf
Eric M. Pashman | 19 Jan 01:13 2013
Picon

Re: Updating/understanding code from implicit configurations paper

Whoops. I forgot you need the explicit `forall` with scoped type variables. I thought there was something
much more involved going on here. Thanks, Shachaf.

Eric

On Jan 18, 2013, at 17:54 , Shachaf Ben-Kiki <shachaf <at> gmail.com> wrote:

> On Fri, Jan 18, 2013 at 3:32 PM, Eric M. Pashman <eric.pashman <at> gmail.com> wrote:
>> 
>>    normalize :: (Modular s a, Integral a) => a -> M s a
>>    normalize x = (M (mod x (modulus (undefined :: s)))) :: M s a
>> 
> 
> If you want your type variables to be scoped, you have to annotate
> them explicitly:
> 
>  normalize :: forall s a. (Modular s a, Integral a) => a -> M s a
>  normalize x = M (mod x (modulus (undefined :: s)))
> 
> See <http://www.haskell.org/ghc/docs/7.4.2/html/users_guide/other-type-extensions.html#scoped-type-variables>.
> 
>    Shachaf

Gmane