вопросы воспроизведения Haskell объектив учебник - PullRequest
1 голос
/ 13 января 2020

Я чувствую, что делаю что-то не так, поскольку мне даже не удается воспроизвести Haskell lens учебник :

> import Control.Lens
> data Point = Point { _x :: Double, _y :: Double } deriving (Show)
> data Atom = Atom { _element :: String, _point :: Point } deriving (Show)
> point = lens _point (\atom newPoint -> atom { _point = newPoint })
> :t point
point :: Functor f => (Point -> f Point) -> Atom -> f Atom
> point :: Lens' Atom Point = lens _point (\atom newPoint -> atom { _point = newPoint })

<interactive>:6:10: error:
    • Illegal polymorphic type: Lens' Atom Point
      Perhaps you intended to use RankNTypes or Rank2Types
    • In a pattern type signature: Lens' Atom Point
      In the pattern: point :: Lens' Atom Point
      In a pattern binding:
        point :: Lens' Atom Point
          = lens _point (\ atom newPoint -> atom {_point = newPoint})
> :set -XRankNTypes
> point :: Lens' Atom Point = lens _point (\atom newPoint -> atom { _point = newPoint })

<interactive>:8:29: error:
    • Couldn't match type ‘(Point -> f0 Point) -> Atom -> f0 Atom’
                     with ‘forall (f :: * -> *).
                           Functor f =>
                           (Point -> f Point) -> Atom -> f Atom’
      Expected type: Lens' Atom Point
        Actual type: (Point -> f0 Point) -> Atom -> f0 Atom
    • In the expression:
        lens _point (\ atom newPoint -> atom {_point = newPoint})
      In a pattern binding:
        point :: Lens' Atom Point
          = lens _point (\ atom newPoint -> atom {_point = newPoint})

Это, безусловно, кажется видя некоторую разницу между f0 против Functor f.

Мой код здесь ничем не отличается от кода в учебном пособии, и никакое количество расширений не спасает меня, насколько я могу судить.

Может быть, у кого-нибудь есть указатели?

1 Ответ

2 голосов
/ 13 января 2020

Я подтвердил предположение в своем комментарии. Это потому, что вы указали тип в шаблоне. Это может быть тривиальное сопоставление с образцом, но это сопоставление с образцом, поскольку оно привязывает имя на LHS =.

, которое даже по умолчанию не разрешено в Haskell. В GH C необходимо включить расширение ScopedTypeVariables, прежде чем оно будет разрешено. И когда вы делаете это, это оказывает странное влияние на полиморфизм. Я не понимаю всех взаимодействий между этим признаком и полиморфизмом более высокого ранга, но он определенно мономорфизирует тип и также ожидает, что он будет полиморфным c. Это просто не сработает.

Я настоятельно рекомендую помещать типы в шаблоны только в том случае, если вы связываете имя для самого типа вместе со значением. Иногда это возникает при работе с экзистенциалами, но я никогда не видел, чтобы это происходило ни в одном другом случае.

В противном случае, просто используйте синтаксис нормального типа для определения типа, даже если вам нужно добавить несколько точек с запятой для заставить его работать в ghci:

point :: Lens' Atom Point ; point = lens _point (\atom newPoint -> atom { _point = newPoint })
...