首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在F#中制作鱼

在F#中制作鱼
EN

Stack Overflow用户
提问于 2017-03-16 01:23:30
回答 1查看 1.3K关注 0票数 7

克莱斯利组合运算符>=>,在Haskell圈子中也被称为“鱼”,在许多需要组合特定函数的情况下可能会派上用场。它的工作原理有点像>>运算符,但它不是组成简单的函数'a -> 'b,而是赋予它们一些特殊的属性,最好用'a -> m<'b>来表示,其中m要么是一个类似monad的类型,要么是函数返回值的某个属性。

在更广泛的F#社区中可以找到这种做法的证据,例如,在Scott Wlaschin的Railway oriented programming (part 2)中,作为返回Result<'TSuccess,'TFailure>类型的函数的组合。

推理出哪里有绑定,哪里就一定有鱼,我试着用绑定函数本身来参数化规范的克莱斯利操作符的定义let (>=>) f g a = f a >>= g

代码语言:javascript
复制
let mkFish bind f g a = bind g (f a)

这非常有效,但需要注意的是,通常不应该在面向用户的代码上释放特殊操作符。我可以编写返回选项的函数...

代码语言:javascript
复制
module Option =
    let (>=>) f = mkFish Option.bind f
    let odd i = if i % 2 = 0 then None else Some i
    let small i = if abs i > 10 then None else Some i
    [0; -1; 9; -99] |> List.choose (odd >=> small)
    // val it : int list = [-1; 9]

..。或者,我可以设计一个对堆栈最顶端的两个值的函数应用程序,并将结果推回,而不必显式引用我正在操作的数据结构:

代码语言:javascript
复制
module Stack =
    let (>=>) f = mkFish (<||) f
    type 'a Stack = Stack of 'a list
    let pop = function
    | Stack[] -> failwith "Empty Stack"
    | Stack(x::xs) -> x, Stack xs
    let push x (Stack xs) = Stack(x::xs)
    let apply2 f =
        pop >=> fun x ->
        pop >=> fun y ->
        push (f x y)

但让我困扰的是,签名val mkFish : bind:('a -> 'b -> 'c) -> f:('d -> 'b) -> g:'a -> a:'d -> 'c毫无意义。类型变量的顺序混乱,过于泛化('a应该是一个函数),而且我没有看到一种自然的方式来注释它。

在没有形式函数器和单体的情况下,我如何在这里进行抽象,而不必为每种类型显式定义克莱斯利运算符?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-16 03:08:51

如果没有更高的种类,你就不能以自然的方式做到这一点。

fish的签名应该是这样的:

代码语言:javascript
复制
let (>=>) (f:'T -> #Monad<'U>``) (g:' U -> #Monad<'V>) (x:'T) : #Monad<'V> = bind (f x) g

这在当前的.NET类型系统中是不能表示的,但您可以用您特定的monad替换#Monad,即:Async,并在实现中使用其相应的绑定函数。

话虽如此,如果你真的想使用一个通用的fish操作符,你可以使用F#+,它已经通过使用静态约束进行了定义。如果你看一下第五个code sample here,你会看到它在不同类型上的作用。

当然,您也可以定义自己的代码,但为了让它在大多数常见场景中都能正常运行,需要编写很多代码。您可以从库中获取代码,或者如果您愿意,我可以编写一个小的(但有限的)代码示例。

通用鱼类是在this line中定义的。

我认为一般来说,在使用运算符时,您确实感觉到缺少泛型函数,因为正如您所发现的,您需要打开和关闭模块。这与函数不同,你可以在函数前面加上模块名,你也可以使用运算符(比如Option.(>=>)),但这样就违背了使用运算符的全部目的,我的意思是,它不再是运算符了。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42816639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档