10

I have been working out on the examples given out in this article for creating Lenses.

I created Lens as stated in the article and the following is my code:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

type Degrees = Double
type Latitude = Degrees
type Longitude = Degrees

data Meetup = Meetup { _name :: String, _location :: (Latitude, Longitude) }
makeLenses ''Meetup

meetupLat = location._1 :: Lens' Meetup Latitude

Now this code doesn't typecheck unless I include this:

{-# LANGUAGE NoMonomorphismRestriction #-}

But no where in the article, I could find out that they have mentioned about the monomorphism restriction. So is this an normal thing or am I doing something wrong here ?

Compiler used: GHC 7.6.2

Sibi
  • 47,472
  • 16
  • 95
  • 163

2 Answers2

11

This is a normal thing. The lens library relies heavily on polymorphism, so the monomorphism restriction (which makes things less polymorphic than they could be) doesn't interact so well with it. In your case, I think you could also write your code like this:

meetupLat :: Lens' Meetup Latitude
meetupLat = location._1

If you provide an explicit polymorphic type signature for a binding, the monomorphism restriction doesn't matter.

Note that Lens' Meetup Latitude is a polymorphic type, even though it looks monomorphic. The type variables are hidden inside the Lens' type synonym. In particular:

Lens' Meetup Latitude is defined as Lens Meetup Meetup Latitude Latitude.

And Lens Meetup Meetup Latitude Latitude is defined as forall f. Functor f => (Meetup -> f Meetup) -> Latitude -> f Latitude

So this is all about the f. I think the monomorphism restriction would force a concrete instantiation of f, but you want to keep it polymorphic because different users of the lens will choose different f. For example view will choose Const and set will choose Identity. So it is really important to keep the f polymorphic to allow the users of the lens these choices.

Toxaris
  • 7,156
  • 1
  • 21
  • 37
4

You just need to specify the type on the function instead of on its definition

meetupLat :: Lens' Meetup Latitude
meetupLat = latitude._1

I believe this is because of the complicated type of Lens' behind the scenes means that while its definition has that type, the compiler still has a hard time guessing that meetupLat has the same type. Maybe someone who has a deeper knowledge of the Monomorphism restriction can elaborate better.

bheklilr
  • 53,530
  • 6
  • 107
  • 163