Haskell 搞乱镜头时出现类型错误
我在编译一些lens代码时遇到了一个类型错误Haskell 搞乱镜头时出现类型错误,haskell,haskell-lens,lenses,Haskell,Haskell Lens,Lenses,我在编译一些lens代码时遇到了一个类型错误 {-# 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)
{-# 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来定义镜头。我怎样才能解决这个问题呢?又是一个可怕的单态性限制的例子。在文件顶部添加
{-#LANGUAGE nomonoromorphismrestriction}
,它就可以正常编译了
原因是当你在没有明确类型签名的情况下(或MR被禁用),让l=ilL进入…时,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
一个显式的类型签名,但是当我们可以让编译器为我们做这一切时,为什么要这么做呢?你同意我把这个问题作为post的副本来结束吗?在这里,我们中的一些人正试图缓解许多问题的问题,这些问题的答案是“关闭DMR”。这不是你的错,如果事先不知道DMR,这个问题在谷歌上很难找到答案。这就是为什么我们试图用一个规范的答案将尽可能多的问题联系在一起,我们试图将大量看似不同的问题汇集到同一个答案中,以便其他人将来能更容易地找到答案。谢谢你的解释,贝克利尔。添加NomonomomorphismRestriction解决了这个问题,尽管添加类型签名Lens'IL[Int]不起作用。@user3458168奇怪,您使用的是什么版本的GHC?这对我来说很好。