Ограничения линз и мономорфизма

Я разработал примеры, приведенные в этой статье для создания объективов.

Я создал Lens, как указано в статье, и следующий код:

{-# 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

Теперь этот код не проверяет тип, если я не включу это:

{-# LANGUAGE NoMonomorphismRestriction #-}

Но нет, где в статье я мог бы узнать, что они упомянули о ограничении мономорфизма. Так что это нормальная вещь, или я здесь что-то не так?

Используемый компилятор: GHC 7.6.2

Ответ 1

Это нормальная вещь. Библиотека lens в значительной степени опирается на полиморфизм, поэтому ограничение мономорфизма (что делает вещи менее полиморфными, чем они могут быть) не так хорошо взаимодействует с ним. В вашем случае, я думаю, вы также можете написать свой код следующим образом:

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

Если вы указываете явную подпись полиморфного типа для привязки, ограничение мономорфизма не имеет значения.

Обратите внимание, что Lens' Meetup Latitude является полиморфным типом, хотя он выглядит мономорфным. Переменные типа скрыты внутри синонима типа Lens'. В частности:

Lens' Meetup Latitude определяется как Lens Meetup Meetup Latitude Latitude.

И Lens Meetup Meetup Latitude Latitude определяется как forall f. Functor f => (Meetup -> f Meetup) -> Latitude -> f Latitude

Итак, это все о f. Я думаю, что ограничение мономорфизма будет приводить к конкретному экземпляру f, но вы хотите сохранить его полиморфным, потому что разные пользователи объектива будут выбирать разные f. Например view выберет Const и set выберет Identity. Поэтому очень важно, чтобы полиморфный f позволял пользователям этого объектива выбирать.

Ответ 2

Вам просто нужно указать тип функции вместо определения

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

Я считаю, что это из-за сложного типа Lens' за кулисами означает, что, хотя его определение имеет этот тип, компилятору все еще сложно угадать, что meetupLat имеет тот же тип. Может быть, кто-то, кто имеет более глубокое знание ограничения мономорфизма, может лучше развиваться.