haskell - 为列表创建一个镜头(类似)

标签 haskell lenses

我正在尝试为以下数据结构创建镜头。我正在使用lens-family .

data Tree = Tree {
        _text :: String,
        _subtrees :: [Tree]
    } deriving (Show,Eq,Read,Generic)

出于各种原因,我想避免使用 Template Haskell。首先,它似乎不适用于我的 ghc 版本(7.8.3),这是另一个(超出范围)问题。

创造记录镜头并不难。

text :: Lens' Tree String
text f (Tree text' subtrees') =
  (\text'' -> Tree text'' subtrees') `fmap` (f text')

subtrees :: Lens' Tree [Tree]
subtrees f (Tree text' subtrees') =
  (\subtrees'' -> Tree text' subtrees'') `fmap` (f subtrees')

但是lens-family似乎没有列表的默认镜头。我认为这是可能的。有lens package 。这些是我失败的尝试:

import Lens.Family2
import Lens.Family2.Unchecked
-- List lenses
_last :: Lens [a] [a'] a a'
_last f l =
  -- first try
  --lens getter setter
  -- second try
  (\el -> (init l) ++ el) `fmap`(f (last l))
  where
    getter = last
    setter l el = l ++ el

他们都收到类似于此的错误:

Could not deduce (a' ~ [a'])
    from the context (Functor f)
      bound by the type signature for
                 _last :: Functor f => LensLike f [a] [a'] a a'
      at editor.hs:22:10-27
      ‘a'’ is a rigid type variable bound by
           the type signature for
             _last :: Functor f => LensLike f [a] [a'] a a'
           at editor.hs:22:10
    Expected type: f [a']
      Actual type: f a'
    Relevant bindings include
      f :: a -> f a' (bound at editor.hs:23:7)
      _last :: LensLike f [a] [a'] a a' (bound at editor.hs:23:1)
    In the second argument of ‘fmap’, namely ‘(f (last l))’
    In the expression: (\ el -> (init l) ++ el) `fmap` (f (last l))

如何定义_last镜头?

编辑:这是构建的版本:

_last f l = (\el -> (init l) ++ [el]) `fmap`(f (last l))

尽管如此,正如 David/Daniel 指出的那样,_last 应该是一个遍历,而不是一个镜头。

最佳答案

您缺少 el 两边的方括号((++) 接受两个参数的列表)。如果你把它们放进去,你的第一次尝试应该会成功。你的类型也太笼统了。列表在 Haskell 中不是异构的,因此它们只能包含一种类型的值。

此外,正如 Daniel Wagner 所说,这不可能是真正的镜头,因为它是局部的。您链接到的镜头文档已过时。目前镜头库有_last as a Traversal这避免了这个问题,因为 Traversal 可以有 0 个或多个目标,而镜头必须恰好有 1 个。

关于haskell - 为列表创建一个镜头(类似),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29591432/

相关文章:

haskell - 为什么这个 Parsec 解析器会进入无限循环?

Haskell 函数不会终止

haskell - flatmap 列表和可能

haskell - 用于 GADT 的 makeLenses (Haskell)

haskell - 如何使用 Lenses 来表示 `mapM` 和 `concat` 以连接 IO 操作的结果?

c++ - 运行时系统如何在已编译的二进制文件上支持 "GC"?

haskell - 如何将 [Maybe Text] 与镜头连接?

haskell - 有条件地修改镜头的目标

haskell - 使用 Lens 过滤复合结构

haskell - 尝试在Haskell中使用存在类型时出现编译错误