haskell 透镜: let binding of Traversal'

标签 haskell traversal haskell-lens

我有点困惑,不知道在哪里寻找以下“问题”的信息/解释(这本身不是问题,但更多的是我不明白出了什么问题的情况幕后):

我有一个带有 StateT 的 monad 转换器堆栈。在我的函数中的某个时刻,我想将状态的一小部分绑定(bind)到局部变量中,这样我就可以引用它,而不是写出我感兴趣的状态 block 的整个路径。这是我的内容意思是:

{-# 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’

但是如果我将此数据 block 的引用移至函数中,那么一切都会编译正常:

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 而言,我们就拥有了与显式类型的绑定(bind)。

someFunction :: MyMonad ()
someFunction = do
  ...
  let x :: Traversal' MyState MyDataT 
      x = myState.clients.ix clientIdx.someData.ix dataIdx
  ...

您第一次尝试的方法很少能达到您的预期:

let x :: Traversal' MyState MyDataT = ...

这是一个没有显式类型的绑定(bind);注释位于左侧内部。 GHC 在查看右侧之前会考虑固定变量的类型,但注释仅适用于左侧,因此 GHC 只是单独推断右侧的类型,然后尝试将其与注释完全匹配。这使得除了最简单的非多态情况之外的所有类型检查都失败。

将注释放入绑定(bind)内的正确方法如下:

let x = ... :: Traversal' MyState MyDataT

这里,GHC 首先将一个“可延展的”不确定类型变量分配给 x ,然后根据那里的注释推断右侧的类型,然后统一 x 的类型用它。

这仍然是一个没有显式类型的绑定(bind),但如果我们启用NoMonomorphismRestriction,它通常可以工作。 ,原因详见SO question .

关于 haskell 透镜: let binding of Traversal',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30725465/

相关文章:

haskell - .~ 的 Monadic 版本(Haskell)

haskell - 类型构造函数可以与值构造函数相同吗?

unit-testing - quickCheckAll 总是返回 "True"

javascript - 遍历 DOM 查找哪个元素获得焦点

jquery遍历和表

haskell - 如何使用镜头列表?

debugging - `derivingUnbox` 不适用于超过 6 个整数的类型

haskell - 我认为 Haskell 中的 Applicative Maybe 实例中的默认定义存在类型不匹配

python - 如何在 Python 中循环 HDF5 组,根据掩码删除行?

haskell - Control.Lens.Setter将类型包装在仿函数中是否不是多余的?