Haskell镜头:让遍历绑定'
Haskell lens: let binding of Traversal'
我有点困惑,不知道去哪里寻找下面"issue"的information/explanation(这本身不是问题,但更多的是我不知道的情况不明白幕后有什么问题):
我有一个带有 StateT 的 monad 转换器堆栈。在我的函数中的某个时刻,我想将我的一小部分状态绑定到局部变量中,这样我就可以引用它,而不是写出我感兴趣的状态块的整个路径。这就是我意思是:
{-# LANGUAGE ScopedTypeVariables #-}
...
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT = myState.clients.ix clientIdx.someData.ix dataIdx
...
现在无法编译:
Couldn't match type ‘(MyDataT -> f0 MyDataT)
-> MyState -> f0 MyState’
with ‘forall (f :: * -> *).
Control.Applicative.Applicative f =>
(MyDataT -> f MyDataT) -> MyState -> f MyState’
但是如果我将这个数据块的引用移动到一个函数中,那么一切都可以编译:
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
我正在寻找某种信息来帮助我理解这里发生了什么,为什么会发生,这样我就知道我做错了什么。基本上我想扩展我的知识以更好地理解这个用例。
这里的重点是注释要单独一行。如果我们这样做,那么就 GHC 而言,我们就有了一个显式类型的绑定。
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT
x = myState.clients.ix clientIdx.someData.ix dataIdx
...
您第一次尝试的很少会像您预期的那样起作用:
let x :: Traversal' MyState MyDataT = ...
这是一个没有显式类型的绑定;注释位于 内部 左侧。 GHC 在查看右侧之前考虑固定变量的类型,但注解仅适用于左侧,因此 GHC 只是单独推断右侧的类型,然后尝试将其与注解完全匹配.这使得除了最简单的非多态情况之外的所有类型检查都失败。
将注释放入绑定的正确方法如下:
let x = ... :: Traversal' MyState MyDataT
这里GHC先给x
分配一个"malleable"不确定类型的变量,然后根据那里的注解推断右边的类型,然后统一x
的类型用它。
这仍然是一个没有显式类型的绑定,但如果我们启用 NoMonomorphismRestriction
,它通常可以正常工作,原因详见 。
我有点困惑,不知道去哪里寻找下面"issue"的information/explanation(这本身不是问题,但更多的是我不知道的情况不明白幕后有什么问题):
我有一个带有 StateT 的 monad 转换器堆栈。在我的函数中的某个时刻,我想将我的一小部分状态绑定到局部变量中,这样我就可以引用它,而不是写出我感兴趣的状态块的整个路径。这就是我意思是:
{-# LANGUAGE ScopedTypeVariables #-}
...
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT = myState.clients.ix clientIdx.someData.ix dataIdx
...
现在无法编译:
Couldn't match type ‘(MyDataT -> f0 MyDataT)
-> MyState -> f0 MyState’
with ‘forall (f :: * -> *).
Control.Applicative.Applicative f =>
(MyDataT -> f MyDataT) -> MyState -> f MyState’
但是如果我将这个数据块的引用移动到一个函数中,那么一切都可以编译:
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
我正在寻找某种信息来帮助我理解这里发生了什么,为什么会发生,这样我就知道我做错了什么。基本上我想扩展我的知识以更好地理解这个用例。
这里的重点是注释要单独一行。如果我们这样做,那么就 GHC 而言,我们就有了一个显式类型的绑定。
someFunction :: MyMonad ()
someFunction = do
...
let x :: Traversal' MyState MyDataT
x = myState.clients.ix clientIdx.someData.ix dataIdx
...
您第一次尝试的很少会像您预期的那样起作用:
let x :: Traversal' MyState MyDataT = ...
这是一个没有显式类型的绑定;注释位于 内部 左侧。 GHC 在查看右侧之前考虑固定变量的类型,但注解仅适用于左侧,因此 GHC 只是单独推断右侧的类型,然后尝试将其与注解完全匹配.这使得除了最简单的非多态情况之外的所有类型检查都失败。
将注释放入绑定的正确方法如下:
let x = ... :: Traversal' MyState MyDataT
这里GHC先给x
分配一个"malleable"不确定类型的变量,然后根据那里的注解推断右边的类型,然后统一x
的类型用它。
这仍然是一个没有显式类型的绑定,但如果我们启用 NoMonomorphismRestriction
,它通常可以正常工作,原因详见