gpt4 book ai didi

interface - 如何使用 F# 在记录结构上定义 fmap

转载 作者:行者123 更新时间:2023-12-04 19:34:51 24 4
gpt4 key购买 nike

是否有可能为记录创建 fmap,以便我可以应用相同的功能来记录类似 bur 不同类型的字段

假设我有一个记录字段类型 Item和记录X和功能 transform

type Item<'a, 'b> = Item of 'a * 'b

let transform (i: Item<'a, 'b>) : Item<'a, string> =
let (Item (x, y)) = i
Item (x, sprintf "%A" y)

type X<'a> = {
y: Item<'a, int>
z: Item<'a, bool>
}
with
member inline this.fmap(f) =
{
y = f this.y
z = f this.z
}

现在是 z = f this.z 行提示给定类型应该是 Item<'a, int>但它的类型为 Item<'a, bool> .显然作为类型推断器
已决定函数 fItem<'a, int> -> Item<...> 类型但是我想要 f应用多态。我怎样才能完成这项工作?

欢迎邪恶类型的黑客攻击!

最佳答案

一个明显的解决方案是使用 bimap而不是 fmap然后在调用者站点编写两次函数:

type Item<'a, 'b> = Item of 'a * 'b

let transform (i: Item<'a, 'b>) : Item<'a, string> =
let (Item (x, y)) = i
Item (x, sprintf "%A" y)

type X<'a> = {
y: Item<'a, int>
z: Item<'a, bool>
}

with
member inline this.bimap(f, g) =
{
y = f this.y
z = g this.z
}

另一种选择(这里是邪恶的类型hack)不是传递一个函数,而是传递我称之为“Invokable”的东西,它用一个名为 Invoke的方法将某种函数包装在一个类型中。 .类似于委托(delegate)但静态的东西。

这是一个例子。我用 $而不是 Invoke为简单起见:
let inline fmap invokable ({y = y1; z = z1}) = {y = invokable $ y1; z = invokable $ z1}


type Id = Id with
static member ($) (Id, Item (a,b)) = Item (id a, id b)

type Default = Default with
static member ($) (Default, Item (a:'t,b:'u)) =
Item (Unchecked.defaultof<'t>, Unchecked.defaultof<'u>)

let a = {y = Item ('1', 2); z = Item ('3', true) }

let b = fmap Id a
let c = fmap Default a

现在的问题是我想不出许多其他有用的功能。你可以吗?

否则,如果你让它更通用:
type X<'a, 'b, 'c> = {
y: Item<'a, 'b>
z: Item<'a, 'c>
}

那么您可以例如使用这样的 Invokable :
type ToList = ToList with static member ($) (ToList, Item (a,b)) = Item ([a], [b])

let d = fmap ToList a
// val d : X<char list,int list,bool list> = {y = Item (['1'],[2]);
z = Item (['3'],[true]);}

另见 this related question .那里提出的案例更简单,但问题是一样的。

还有 this one相关的。

关于interface - 如何使用 F# 在记录结构上定义 fmap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41123405/

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