gpt4 book ai didi

Haskell 光学器件 : Setter for several lists

转载 作者:行者123 更新时间:2023-12-05 03:18:46 25 4
gpt4 key购买 nike

我想在两个列表之间的 x 位置设置一个项目,就好像它们是同一个列表一样。例如:

data Foo = Foo {
list1 :: [Char],
list2 :: [Char]}

foo = Foo ['a', 'b', 'c'] ['d', 'e', 'f']

setItem :: Int -> Char -> Foo -> Foo
setItem i c f = ???

例如,将元素设置在位置 5 会产生:

setItem 5 'X' foo 
==> Foo ['a', 'b', 'c'] ['d', 'X', 'f']

我想我可以为此使用光学/镜头。类似的东西(使用光学和标签):

setItem :: Int -> Char -> Foo -> Foo
setItem i c f = set ((#list1 <> #list2) % at i) c f

但这行不通:

No instance for (Semigroup (Optic k1 NoIx s0 t0 v0 v0))

最佳答案

我已经研究了如何使用光学器件来实现这一点,您需要使用 adjoin 将两个镜头结合起来,然后您可以使用 elementOf 遍历具有特定索引的元素。 .

这些可以组合如下:

我将从完整地写出导入和数据声明开始:

{-# Language TemplateHaskell #-}
{-# Language OverloadedLabels #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

import Optics
import Optics.Label
import Optics.IxTraversal

data Foo = Foo {
list1 :: [Char],
list2 :: [Char]
} deriving Show

makeFieldLabelsNoPrefix ''Foo
foo = Foo ['a', 'b', 'c'] ['d', 'e', 'f']

那么实际的功能是这样的:

setItem :: Int -> Char -> Foo -> Foo
setItem i c f = set (((#list1 `adjoin` #list2) % traversed) `elementOf` i) c f

需要注意的两件事是,adjoin 的正确使用依赖于两个镜头的目标是不相交的;您不应该将它与作为不同参数的相同镜头(或具有重叠目标的镜头)一起使用。

elementOf遍历遍历的第n个元素;它不尊重 IxTraversal 的索引, 它需要任何旧的 Traversal并使用该遍历中每个元素的位置作为索引。

关于Haskell 光学器件 : Setter for several lists,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73614965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com