ksa*_*jev 3 haskell traversal haskell-lens
我有点困惑,不知道在哪里寻找下面的"问题"的信息/解释(这本身不是问题,但更多的是我不明白背后有什么问题的情况):
我有一个带StateT的monad变换器堆栈.在我的函数中的某个时刻,我想将我的一小部分状态绑定到局部变量中,所以我可以引用它而不是写出我感兴趣的状态块的整个路径.这就是我的意思意思:
{-# LANGUAGE ScopedTypeVariables #-}
...
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT = myState.clients.ix clientIdx.someData.ix dataIdx
...
Run Code Online (Sandbox Code Playgroud)
现在这不编译:
Couldn't match type ‘(MyDataT -> f0 MyDataT)
-> MyState -> f0 MyState’
with ‘forall (f :: * -> *).
Control.Applicative.Applicative f =>
(MyDataT -> f MyDataT) -> MyState -> f MyState’
Run Code Online (Sandbox Code Playgroud)
但是如果我将这个数据块的引用移动到一个函数中,那么一切都可以编译好:
someFunction :: MyMonad ()
someFunction = do
...
let x = clientData clientIdx dataIdx
...
where clientData :: Int -> Int -> Traversal' MyState MyDataT
clientData clientIdx dataIdx = myState.clients.ix clientIdx.someData.ix dataIdx
Run Code Online (Sandbox Code Playgroud)
我正在寻找某种信息,这些信息可以帮助我理解这里发生了什么,为什么会发生这种情况,以便我知道我做错了什么.基本上我想扩展我的知识,以便更好地理解这个用例.
这里的关键点是注释应该在一个单独的行中.如果我们这样做,那么就GHC而言,我们有一个明确类型的绑定.
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT
x = myState.clients.ix clientIdx.someData.ix dataIdx
...
Run Code Online (Sandbox Code Playgroud)
你第一次尝试的东西很少像你想象的那样工作:
let x :: Traversal' MyState MyDataT = ...
Run Code Online (Sandbox Code Playgroud)
这是一个没有显式类型的绑定; 注释位于左侧.GHC在查看右侧之前考虑固定变量的类型,但是注释仅适用于左侧,因此GHC只是分别为右侧有一个类型,然后尝试将其与注释完全匹配.除了最简单的非多态情况之外,这使得类型检查失败.
将注释放在绑定中的正确方法如下:
let x = ... :: Traversal' MyState MyDataT
Run Code Online (Sandbox Code Playgroud)
在这里,GHC首先分配一个"可塑的"不确定类型变量x,然后通过那里的注释推断右侧的类型,然后统一其类型x.
这仍然是一个没有显式类型的绑定,但是如果我们启用它,它会起作用NoMonomorphismRestriction,原因在于这个SO问题中详述的原因.