如何在F#中编写可变参数函数以模拟类似的Haskell解决方案? [英] How to write a variadic function in F# emulating a similar Haskell solution?

查看:66
本文介绍了如何在F#中编写可变参数函数以模拟类似的Haskell解决方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我(如果有的话)如何模拟 variadic函数(不是方法),以便我可以编写

How can I (if at all) emulate variadic functions (not methods) so that I could write

sum 1 2 3
sum 1 2 3 4 5
sum 1 2 3 4 5 6 7
// etc.

上面的代码只是作为示例的意思-显然,如果我必须对列表进行汇总

The code above is just meant as an example - obviously if I would have to sum up a list then

[ 1; 2 ; 3] |> List.sum 

是更好的方法.

但是我正在寻找结构上类似的 解决方案,例如这个Haskell解决方案

However I am looking for a structurally similar solution like this Haskell solution

同样重要的是,函数调用和参数值的 normal 语法保持不变.所以

What is also important is that the normal syntax for function calls and parameter values remains the same. So

sum 1 2 3

vs

sum(1, 2, 3)

这实际上意味着

let sum ([<ParamArray>] arr) = ...

在此特定情况下不希望使用

.

is not wanted in this specific case.

所有这些的动机:我正在探索F#的类型系统和语法的外部边缘.而且我完全意识到,我可能已经超越了可能的界限.

The motivation for all of this: I am exploring the outer fringes of F#'s type system and syntax. And I am fully aware of that I might have crossed the boundary of what is possible already.

PS:我的具体想法(在此未描述)也可以完全不同地解决-所以我知道,所以我已经做到了. 因此,我的问题不是:如何以不同的方式解决这个问题,而又如何像Haskell那样在结构上解决问题.

PS: my concrete ideas (which I have not described here) can also be solved completely differently - so I know and so I have done already. Therefore my question is not: how can this be solved differently but how can this be solved structurally like Haskell.

PPS:如果您可以使整个解决方案递归,则加倍Karma点.

PPS: Double Karma-Points if you can make the whole solution recursive.

推荐答案

您说的是函数,而不是方法.因此ParamArray不是一个选择.

You said function, not method. So ParamArray is not an option.

您链接的Haskell代码基于推断的结果类型.

The Haskell code you linked is based on the inferred result type.

这是一种根据F#中推断的结果类型进行解析的方法:

Here's a way to resolve based on the inferred result type in F#:

type T = T with
    static member inline ($) (T, r:'t->'t        ) = fun a b     -> a + b
    static member inline ($) (T, r:'t->'t->'t    ) = fun a b c   -> a + b + c
    static member inline ($) (T, r:'t->'t->'t->'t) = fun a b c d -> a + b + c + d

let inline sum (x:'a) :'r = (T $ Unchecked.defaultof<'r>) x

let x:int = sum 2 3 
let y:int = sum 2 3 4
let z:int = sum 2 3 4 5
let d:decimal = sum 2M 3M 4M

let mult3Numbers a b c = a * b * c
let res2 = mult3Numbers 3 (sum 3 4  ) 10
let res3 = mult3Numbers 3 (sum 3 4 5) 10

更新

上面的代码从F#4.1起不再起作用(请参见注释),但这是一个使用n个(无限个)参数的递归多变量函数的更好示例:

The above code doesn't work anymore as from F# 4.1 (see the comments) but here's a better example with a recursive polyvariadic function taking n (unlimited) arguments:

type T = T with
    static member        ($) (T, _:int    ) = (+)
    static member        ($) (T, _:decimal) = (+)

let inline sum (i:'a) (x:'a) :'r = (T $ Unchecked.defaultof<'r>) i x

type T with
    static member inline ($) (T, _:'t-> 'rest) = fun (a:'t) -> (+) a >> sum


let x:int = sum 2 3 
let y:int = sum 2 3 4
let z:int = sum 2 3 4 5
let d:decimal = sum 2M 3M 4M

let mult3Numbers a b c = a * b * c
let res2 = mult3Numbers 3 (sum 3 4) (sum 2 2 3 3)
let res3 = mult3Numbers 3 (sum 3 4 5 11 13 20) 10

您还可以查看多变量折叠.

这篇关于如何在F#中编写可变参数函数以模拟类似的Haskell解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆