gpt4 book ai didi

haskell - 如何迭代具有相同类型的记录类型中的所有元素(记录类型的纯函数迭代器)

转载 作者:行者123 更新时间:2023-12-01 23:46:59 25 4
gpt4 key购买 nike

有没有一种很好的方法来迭代、折叠或循环记录中具有相同类型的所有元素?例如,在下面的 OCaml 代码中

type foo = {
a : int;
b : float;
c : int;
d : float
}

let foo = {
a = 1;
b = 2.0;
c = 3;
d = 4.0
}

我想分别遍历所有整数或 float 。我知道 Fieldslib,但它似乎没有做我想做的事。例如,使用 Fieldslib,我可以编写代码:

open Fieldslib
type bar = {
w : int;
x : float;
y : int;
z : float
} with fields

let bar = {
w = 1;
x = 2.0;
y = 3;
z = 4.0
}

let print_int bar x = Printf.printf "%d\n" (Fieldslib.Field.get x bar)

let print_float bar x = Printf.printf "%f\n" (Fieldslib.Field.get x bar);;

Fields_of_bar.iter ~w:(print_int bar)
~x:(print_float bar)
~y:(print_int bar)
~z:(print_float bar)

但这迫使我们遍历所有元素,而不仅仅是单独的整数或 float 。它还要求分别指定要在每个元素上调用的函数。真的,我只想说对结构进行迭代、映射或折叠某些函数。

如果异构记录类型很难做到这一点,那么所有元素都具有单一类型的记录类型会更容易吗?在这种情况下,我们可以定义一个镜头来转换出所有的整数、 float 等。

从某种意义上说,感觉我想要某种与记录类型一起工作的纯函数迭代器,如果存在这样的技术,我不确定它叫什么。


编辑 1

实际上,这可能比我想象的要简单得多。 Fieldslib 已经给出了一流的元素。只要我们列出所有具有相同类型的列表,我们就可以了。换句话说:

open Fieldslib
type bar = {
w : int;
x : float;
y : int;
z : float
} with fields

let ints=[w;y]
let floats=[x;z]

let bar = {
w = 1;
x = 2.0;
y = 3;
z = 4.0
};;

let print_ints bar = List.iter (fun l -> Printf.printf "%d\n" (l bar)) ints
let print_floats bar = List.iter (fun l -> Printf.printf "%f\n" (l bar)) floats

更一般地说,具有相同类型的镜头列表应该使所有这一切成为可能,因为我们可以只应用列表中的 map、fold 和 iter 函数。


编辑2

如果有人想运行@j-abrahamson 的代码,这里有一些轻微的修改,以便它在我的机器上运行

{-# LANGUAGE RankNTypes #-}

import Control.Applicative
import Control.Monad.Identity

data Foo = Foo {
a :: Int,
b :: Float,
c :: Int,
d :: Float
} deriving Show

type Traversal s a = forall f . Applicative f => (a -> f a) -> (s -> f s)

intsOfFoo :: Traversal Foo Int
intsOfFoo inj foo = build <$> inj (a foo) <*> inj (c foo) where
build a c = foo { a = a, c = c }

mapOf :: Traversal s a -> (a -> a) -> (s -> s)
mapOf trav f = runIdentity . trav (Identity . f)

foo0 = Foo { a = 1, b = 1, c = 1, d = 1 }

foo1 = mapOf intsOfFoo (+1) foo0

我还添加了 Haskell 标志,以防这对其他人有帮助。

最佳答案

实际上,这可能比我想象的要简单得多。 Fieldslib 已经给出了一流的元素。只要我们列出所有具有相同类型的列表,我们就可以了。换句话说:

open Fieldslib
type bar = {
w : int;
x : float;
y : int;
z : float
} with fields

let ints=[w;y]
let floats=[x;z]

let bar = {
w = 1;
x = 2.0;
y = 3;
z = 4.0
};;

let print_ints bar = List.iter (fun l -> Printf.printf "%d\n" (l bar)) ints
let print_floats bar = List.iter (fun l -> Printf.printf "%f\n" (l bar)) floats

更一般地说,具有相同类型的镜头列表应该使所有这一切成为可能,因为我们可以只应用列表中的 map、fold 和 iter 函数。

关于haskell - 如何迭代具有相同类型的记录类型中的所有元素(记录类型的纯函数迭代器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28662358/

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