gpt4 book ai didi

haskell - 关联列表的镜头

转载 作者:行者123 更新时间:2023-12-04 17:20:40 24 4
gpt4 key购买 nike

Control.Lens.At 中有at lens for Map/HashMap/etc。但是对于关联列表类型 [(k, v)](可转换为 map),是否有类似于 at 的镜头?

最佳答案

我不知道有没有为您提供的,但是 at 属于类型类 At,因此我们当然可以自己编写。为了避免弄脏我们的手来处理灵活的(并且可能重叠的)实例扩展,我们将在新类型中执行此操作。

newtype AList k v = AList [(k, v)]

首先,我们需要几个家庭实例。

{-# LANGUAGE TypeFamilies #-}

type instance IxValue (AList k v) = v
type instance Index (AList k v) = k

这只是定义了我们新类型中的“键”和“值”,这很简单。现在,我们需要能够在特定键上读取和写入值。 Haskell 已经为我们提供了一种读取值的方法(Data.List.lookup),但我们必须自己编写写入函数。这里没有什么花哨的东西或 lens-y:只是普通的旧 Haskell 过滤器和贴图。

replaceAt :: Eq k => k -> Maybe v -> AList k v -> AList k v
replaceAt k Nothing (AList m) = AList $ filter (\(k', _) -> k /= k') m
replaceAt k (Just v) (AList m) =
case lookup k m of
Nothing ->
-- Not present in the list; add it
AList ((k, v) : m)
Just _ ->
-- Present; replace it
AList $ map (\(k', v') -> if k == k' then (k', v) else (k', v')) m

现在我们需要编写At实例,它依赖于Ixed实例。幸运的是,镜头库为 Ixed 提供了一个默认实现,只要我们正在实现 At,所以第一个实例声明很简单。

instance Eq k => Ixed (AList k v)

编写 at 也相当简单。只需查看类型并稍稍跟着你的 Nose 走,你得到的实现就是我们想要的。

instance Eq k => At (AList k v) where
at k f (AList m) = fmap (\v' -> replaceAt k v' (AList m)) $ f (lookup k m)

我们完成了。现在 at 将适用于 AList。如果 newtype 包装器困扰你,你可以很容易地创建一个新函数(at',如果你愿意)为你做 newtype 包装/解包。

证明此实例满足透镜定律留给读者作为练习。

完整代码

{-# LANGUAGE TypeFamilies #-}

import Control.Lens.At
import Data.List(lookup)

newtype AList k v = AList [(k, v)]

type instance IxValue (AList k v) = v
type instance Index (AList k v) = k

replaceAt :: Eq k => k -> Maybe v -> AList k v -> AList k v
replaceAt k Nothing (AList m) = AList $ filter (\(k', _) -> k /= k') m
replaceAt k (Just v) (AList m) =
case lookup k m of
Nothing ->
-- Not present in the list; add it
AList ((k, v) : m)
Just _ ->
-- Present; replace it
AList $ map (\(k', v') -> if k == k' then (k', v) else (k', v')) m

-- Just take the default implementation here.
instance Eq k => Ixed (AList k v)

instance Eq k => At (AList k v) where
at k f (AList m) = fmap (\v' -> replaceAt k v' (AList m)) $ f (lookup k m)

关于haskell - 关联列表的镜头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55264120/

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