Roman Cheplyaka | 22 Mar 09:39 2013

ImplicitParams and MonoLocalBinds

The value of the following expression

  let ?y = 2  in
  let  p = ?y in
  let ?y = 1  in
  p

depends on whether the second binding is generalised.

MonomorphismRestriction makes it not generalise, hence the value is 2.

What surprises me is that MonoLocalBinds doesn't have this effect.

  Prelude> :set -XImplicitParams -XNoMonomorphismRestriction -XMonoLocalBinds 
  Prelude> let ?y = 2 in let p = ?y in let ?y = 1 in p
  1

What's going on here?

Roman
Iavor Diatchki | 29 Mar 00:39 2013
Picon

Re: ImplicitParams and MonoLocalBinds

Hi,
This does not appear to be related to ImplicitParameters, rather `MonoLocalBinds` is not working as expected.

Here is an example without implicit parameters that compiles just fine, but would be rejected if `p` was monomorphic:

{-# LANGUAGE NoMonomorphismRestriction, MonoLocalBinds #-}

class C a where
  f :: a -> ()

instance C Bool where f = const ()
instance C Char where f = const ()

g = let p = f
    in (p 'a', p True)

-Iavor




On Fri, Mar 22, 2013 at 1:39 AM, Roman Cheplyaka <roma <at> ro-che.info> wrote:
The value of the following expression

  let ?y = 2  in
  let  p = ?y in
  let ?y = 1  in
  p

depends on whether the second binding is generalised.

MonomorphismRestriction makes it not generalise, hence the value is 2.

What surprises me is that MonoLocalBinds doesn't have this effect.

  Prelude> :set -XImplicitParams -XNoMonomorphismRestriction -XMonoLocalBinds
  Prelude> let ?y = 2 in let p = ?y in let ?y = 1 in p
  1

What's going on here?

Roman

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Iavor Diatchki | 29 Mar 01:07 2013
Picon

Re: ImplicitParams and MonoLocalBinds

Hi,

Aha! This page explains what is going on: http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7

The summary is that the definition of what is "local" is not what one might expect:  only things that depend
on variables in scope are considered to be locals, other bindings, that could be lifted out (e.g., like `p` in both examples)
are not considered local and are generalized.  Of course, with implicit parameters this is not what one might hope for...

A while back there was a discussion about adding a construct for monomorphic bindings to the language (I think the proposed notation was something like "x := 2").
Perhaps we should revisit it, it seems much simpler than the rather surprising behavior of `MonoLocalBinds`.

-Iavor






On Thu, Mar 28, 2013 at 4:39 PM, Iavor Diatchki <iavor.diatchki <at> gmail.com> wrote:
Hi,
This does not appear to be related to ImplicitParameters, rather `MonoLocalBinds` is not working as expected.

Here is an example without implicit parameters that compiles just fine, but would be rejected if `p` was monomorphic:

{-# LANGUAGE NoMonomorphismRestriction, MonoLocalBinds #-}

class C a where
  f :: a -> ()

instance C Bool where f = const ()
instance C Char where f = const ()

g = let p = f
    in (p 'a', p True)

-Iavor




On Fri, Mar 22, 2013 at 1:39 AM, Roman Cheplyaka <roma <at> ro-che.info> wrote:
The value of the following expression

  let ?y = 2  in
  let  p = ?y in
  let ?y = 1  in
  p

depends on whether the second binding is generalised.

MonomorphismRestriction makes it not generalise, hence the value is 2.

What surprises me is that MonoLocalBinds doesn't have this effect.

  Prelude> :set -XImplicitParams -XNoMonomorphismRestriction -XMonoLocalBinds
  Prelude> let ?y = 2 in let p = ?y in let ?y = 1 in p
  1

What's going on here?

Roman

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users


_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Roman Cheplyaka | 29 Mar 07:38 2013

Re: ImplicitParams and MonoLocalBinds

Right! I knew about this, but somehow it didn't pop up in my mind in
this case. Thanks a lot!

Roman

* Iavor Diatchki <iavor.diatchki <at> gmail.com> [2013-03-28 17:07:18-0700]
> Hi,
> 
> Aha! This page explains what is going on:
> http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7
> 
> The summary is that the definition of what is "local" is not what one might
> expect:  only things that depend
> on variables in scope are considered to be locals, other bindings, that
> could be lifted out (e.g., like `p` in both examples)
> are not considered local and are generalized.  Of course, with implicit
> parameters this is not what one might hope for...
> 
> A while back there was a discussion about adding a construct for
> monomorphic bindings to the language (I think the proposed notation was
> something like "x := 2").
> Perhaps we should revisit it, it seems much simpler than the rather
> surprising behavior of `MonoLocalBinds`.
> 
> -Iavor
> 
> 
> 
> 
> 
> 
> On Thu, Mar 28, 2013 at 4:39 PM, Iavor Diatchki <iavor.diatchki <at> gmail.com>wrote:
> 
> > Hi,
> > This does not appear to be related to ImplicitParameters, rather
> > `MonoLocalBinds` is not working as expected.
> >
> > Here is an example without implicit parameters that compiles just fine,
> > but would be rejected if `p` was monomorphic:
> >
> > {-# LANGUAGE NoMonomorphismRestriction, MonoLocalBinds #-}
> >
> > class C a where
> >   f :: a -> ()
> >
> > instance C Bool where f = const ()
> > instance C Char where f = const ()
> >
> > g = let p = f
> >     in (p 'a', p True)
> >
> > -Iavor
> >
> >
> >
> >
> > On Fri, Mar 22, 2013 at 1:39 AM, Roman Cheplyaka <roma <at> ro-che.info> wrote:
> >
> >> The value of the following expression
> >>
> >>   let ?y = 2  in
> >>   let  p = ?y in
> >>   let ?y = 1  in
> >>   p
> >>
> >> depends on whether the second binding is generalised.
> >>
> >> MonomorphismRestriction makes it not generalise, hence the value is 2.
> >>
> >> What surprises me is that MonoLocalBinds doesn't have this effect.
> >>
> >>   Prelude> :set -XImplicitParams -XNoMonomorphismRestriction
> >> -XMonoLocalBinds
> >>   Prelude> let ?y = 2 in let p = ?y in let ?y = 1 in p
> >>   1
> >>
> >> What's going on here?
> >>
> >> Roman
> >>
> >> _______________________________________________
> >> Glasgow-haskell-users mailing list
> >> Glasgow-haskell-users <at> haskell.org
> >> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
> >>
> >
> >
Simon Peyton-Jones | 3 Apr 19:43 2013
Picon

RE: ImplicitParams and MonoLocalBinds

Correct.  Maybe the flag should be called “MonoOpenBinds”!

 

Really, the simplest solution is to write a type signature.  Then all is clear.

 

I’m very open to adding something to the documentation to explain about this. The current section is below... concrete suggestions for improvement would be welcome.

 

Simon

 

 

 

7.12.10. Let-generalisation

An ML-style language usually generalises the type of any let-bound or where-bound variable, so that it is as polymorphic as possible. With the flag -XMonoLocalBinds GHC implements a slightly more conservative policy: it generalises only "closed" bindings. A binding is considered "closed" if either

  • It is one of the top-level bindings of a module, or

  • Its free variables are all themselves closed

For example, consider

f x = x + 1

g x = let h y = f y * 2

          k z = z+x

      in  h x + k x

Here f and g are closed because they are bound at top level. Also h is closed because its only free variable f is closed. But k is not closed because it mentions x which is locally bound. Another way to think of it is this: all closed bindings could be defined at top level. (In the example, we could move h to top level.)

All of this applies only to bindings that lack an explicit type signature, so that GHC has to infer its type. If you supply a type signature, then that fixes type of the binding, end of story.

The rationale for this more conservative strategy is given in the papers "Let should not be generalised" and "Modular type inference with local assumptions", and a related blog post.

The flag -XMonoLocalBinds is implied by -XTypeFamilies and -XGADTs. You can switch it off again with -XNoMonoLocalBinds but type inference becomes less predicatable if you do so. (Read the papers!)

 

 

 

From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-users-bounces <at> haskell.org] On Behalf Of Iavor Diatchki
Sent: 29 March 2013 00:07
To: Roman Cheplyaka
Cc: GHC Users Mailing List
Subject: Re: ImplicitParams and MonoLocalBinds

 

Hi,

 

Aha! This page explains what is going on: http://hackage.haskell.org/trac/ghc/blog/LetGeneralisationInGhc7

 

The summary is that the definition of what is "local" is not what one might expect:  only things that depend

on variables in scope are considered to be locals, other bindings, that could be lifted out (e.g., like `p` in both examples)

are not considered local and are generalized.  Of course, with implicit parameters this is not what one might hope for...

 

A while back there was a discussion about adding a construct for monomorphic bindings to the language (I think the proposed notation was something like "x := 2").

Perhaps we should revisit it, it seems much simpler than the rather surprising behavior of `MonoLocalBinds`.

 

-Iavor

 

 

 

 

 

On Thu, Mar 28, 2013 at 4:39 PM, Iavor Diatchki <iavor.diatchki <at> gmail.com> wrote:

Hi,

This does not appear to be related to ImplicitParameters, rather `MonoLocalBinds` is not working as expected.

 

Here is an example without implicit parameters that compiles just fine, but would be rejected if `p` was monomorphic:

 

{-# LANGUAGE NoMonomorphismRestriction, MonoLocalBinds #-}

 

class C a where

  f :: a -> ()

 

instance C Bool where f = const ()

instance C Char where f = const ()

 

g = let p = f

    in (p 'a', p True)

 

-Iavor

 

 

 

On Fri, Mar 22, 2013 at 1:39 AM, Roman Cheplyaka <roma <at> ro-che.info> wrote:

The value of the following expression

  let ?y = 2  in
  let  p = ?y in
  let ?y = 1  in
  p

depends on whether the second binding is generalised.

MonomorphismRestriction makes it not generalise, hence the value is 2.

What surprises me is that MonoLocalBinds doesn't have this effect.

  Prelude> :set -XImplicitParams -XNoMonomorphismRestriction -XMonoLocalBinds
  Prelude> let ?y = 2 in let p = ?y in let ?y = 1 in p
  1

What's going on here?

Roman

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

 

 

_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

Gmane