2015-04-23 2 views
1

У меня возникает ошибка типа при попытке скомпилировать код объектива.Ошибка типа при работе с объективами

{-# LANGUAGE TemplateHaskell #-} 

import Control.Lens.Setter (over) 
import Control.Lens.Getter (view) 
import Control.Lens.TH 

data IL = IL { 
    _ilL :: [Int] 
} 
    deriving (Show) 

makeLenses ''IL 

val = IL [1, 2, 3] 

(val1, val2) = let l = ilL 
     in (over l tail val, view l val) 

Ошибка:

Test.hs:17:35: 
    Couldn't match expected type `Control.Lens.Internal.Getter.Accessor [Int] [Int]' 
       with actual type `Control.Lens.Internal.Setter.Mutator [Int]' 
    Expected type: Control.Lens.Getter.Getting [Int] s0 [Int] 
     Actual type: ([Int] 
        -> Control.Lens.Internal.Setter.Mutator [Int]) 
        -> IL -> Control.Lens.Internal.Setter.Mutator IL 
    In the first argument of `view', namely `l' 
    In the expression: view l val 

Эта ошибка уходит, если я использую Ill непосредственно. Тем не менее, мне действительно нужно сделать определение объектива, используя let. Как я могу это решить?

+5

Вы согласны с тем, что я закрываю этот вопрос как дубликат [this] (http://stackoverflow.com/a/7055932/1651941)? Пара из нас здесь, на SO, пытается решить проблему стольких вопросов, ответ на который «Отключите DMR». Это не ваша вина, этот вопрос действительно трудно найти ответ на Google без предварительного знания DMR. Вот почему мы пытаемся связать как можно больше вопросов с одним каноническим ответом, мы пытаемся вызвать большое количество, казалось бы, разных вопросов к одному и тому же ответу, чтобы другим было легче в будущем. – bheklilr

+0

Пожалуйста, вперед. – user3458168

ответ

2

Еще один случай страшного ограничения мономорфизма. Добавьте {-# LANGUAGE NoMonormorphismRestriction #-} в начало вашего файла, и он скомпилируется просто отлично.

Причина в том, что, когда вы делаете let l = ilL in ... без явной подписи типа (или с отключенным MR) GHC хочет специализироваться на типе l насколько это возможно. Он впервые встречает его использование в over l tail val и специализируется на типе, который там нужен, но это противоречит специализированному выведенному типу в view l val. Решение состоит в том, чтобы отключить MR или добавить явные сигнатуры типов, как

(val1, val2) = 
    let l :: Lens' IL [Int] 
     l = ilL 
    in (over l tail val, view l val) 

Это очень похоже на более простом случае, как

x = let y = 1 
     z = 2 :: Int 
     w = 3 :: Double 
    in (z + y, w + y) 

Что тип y должен быть? С MR компилятор хочет ограничить тип y одним типом, но нам бы очень хотелось, чтобы он имел тип Num a => a, так как он может работать с Int s или Double s. При выключенном MR компилятор не будет специализироваться на типе y, и все работает так, как ожидалось. Альтернативой является дать y явную подпись типа, но зачем все это работает, когда мы можем заставить компилятор сделать это для нас?

+0

Спасибо за объяснение, bekler. Добавление NoMonomorphismRestriction решило проблему, хотя добавление сигнатуры типа Lens 'IL [Int] не сработало. – user3458168

+0

@ user3458168 Странно, какая версия GHC вы используете? Это сработало для меня отлично. – bheklilr

Смежные вопросы