gpt4 book ai didi

f# - 如何用条件实现 List Monad(计算表达式)?

转载 作者:行者123 更新时间:2023-12-04 22:28:41 24 4
gpt4 key购买 nike

我试图了解如何使用 F# 计算表达式,这确实让我感到困惑。

下面的例子对我有一定的意义。

type ListMonad() =
member o.Bind( (m:'a list), (f: 'a -> 'b list) ) = List.collect f m
member o.Return(x) = [x]

let list = ListMonad()

let test =
list {
let! x = [ 1 .. 10]
let! y = [2 .. 2 .. 20]
return (x,y)
}

我的问题是,您将如何向此计算表达式添加条件?具体来说,您将如何更改它以仅返回 x 值严格小于 y 值的元素列表? (我们以后不要过滤掉它)。

最佳答案

computation expressions can be parameterized ,你可能首先想到尝试这样的事情:

let filterAndCollect (pred : 'a -> 'b -> bool) (f : 'a -> 'b list) (m : 'a list) =
let f' a = [ for b in f a do if pred a b then yield b ]
List.collect f' m

type FilteringListMonad(pred) =
member o.Bind( (m:'a list), (f: 'a -> 'b list) ) = filterAndCollect pred f m
member o.Return(x) = [x]

let filteredList = FilteringListMonad(fun x y -> x < y)

let test2 =
filteredList {
let! x = [1 .. 10]
let! y = [2 .. 2 .. 20]
return (x,y)
}

但是,这会失败并在 (x,y) 上出现类型错误。元组:

This expression was expected to have type 'int' but here has type ''a * 'b'



还有两个编译器警告: yx < y FilteringListMonad 构造函数中的表达式,有一个警告:

This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type ''b'.



和号码 1let! x = [1 .. 10]表达式,有一个警告:

This construct causes code to be less generic than indicated by the type annotations. The type variable 'b has been constrained to be type 'int'.



因此,在这两个约束之间,计算表达式( 'b list)的返回类型已被约束为 int list ,但您的表达式返回 int * int list反而。在考虑了类型约束之后,您可能会得出这样的结论:这是行不通的。 但有一种方法可以让它发挥作用。 关键是要意识到 'b在本例中,将作为计算表达式输出的类型实际上是元组 int * int , 所以你重写谓词函数实际上只取 'b输入,然后一切正常:
let filterAndCollect (pred : 'b -> bool) (f : 'a -> 'b list) (m : 'a list) =
let f' a = [ for b in f a do if pred b then yield b ]
List.collect f' m

type FilteringListMonad(pred) =
member o.Bind( (m:'a list), (f: 'a -> 'b list) ) = filterAndCollect pred f m
member o.Return(x) = [x]

let filteredList = FilteringListMonad(fun (x:int,y:int) -> x < y)

let test2 =
filteredList {
let! x = [ 1 .. 10]
let! y = [2 .. 2 .. 20]
return (x,y)
}

请注意,我还必须指定谓词函数输入的类型。没有它,F# 将它们概括为“实现 System.IComparable 的任何类型,但我传入了 int s,它们是值类型,因此不实现任何接口(interface)。这导致了错误

This expression was expected to have type 'System.IComparable' but here has type 'int'.



但是,将谓词的两个参数声明为 int成功了。

关于f# - 如何用条件实现 List Monad(计算表达式)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43692084/

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