2010-05-08 87 views
6

这不是一个实际的重要问题,但我希望在F#中看到一个tacit programming的例子,其中我的函数可以有多个参数(不是以列表或元组的形式) 。使用F的默认编程风格#

其次,这些功能如何操纵复杂数据结构。我正在F#Interactive上试用它,但还没有成功。

我试过,例如:

> (fun _ -> (fun _ -> (+))) 333 222 111 555 

是不是正确的方式?

和:

> (fun _ -> (fun _ -> (+))) "a" "b" "c" "d";; 

val it : string = "cd" 
+3

你应该使用“无点”而不是“无意义”。这是标准术语。 :) – 2010-06-04 03:19:04

回答

4

F#不包含一些在哈斯克尔(主要是因为F#程序员通常更喜欢编程的明确的风格,只在最明显的情况下,使用pointfree风格中提供的基本功能,它不会影响可读性)。

但是你可以定义这样几个基本的组合子:

// turns curried function into non-curried function and back 
let curry f (a, b) = f a b 
let uncurry f a b = f (a, b) 

// applies the function to the first/second element of a tuple 
let first f (a, b) = (f a, b) 
let second f (a, b) = (a, f b) 

现在,您可以实现添加使用组合算符两个字符串的长度的功能如下:

let addLengths = 
    uncurry (((first String.length) >> (second String.length)) >> (curry (+))) 

这种构造两个功能将String.length应用于元组的第一个/第二个元素,然后进行组合,然后使用+添加元组的元素。整个东西被包装在uncurry中,所以你得到string -> string -> int类型的功能。

+0

我检查了在FSI,它确实工作!非常感谢你;顺便说一句,你能解释你是如何得到这个元组函数组合语法的?我的意思是'(第一个String.length)>>(第二个String.length)'这对我来说看起来有些不寻常;) – Bubba88 2010-05-08 17:53:44

+0

这是用函数组合'>>'实现的。例如'f >> g'表示对于参数'x',它将调用'g(f(x))'。在上面的例子中,第一个函数('first String.length')将一个元组“string * string”变成一个元组“int * string”,而第二个函数('second String.length')将其变成'int * int'包含长度。 – 2010-05-08 18:02:24

+0

你实际上正在为F#实施箭头;)好吧,为什么不 - 箭发明是作为monads和默认编程的组合发明的。 – Dario 2010-08-10 15:30:08

2

在F#中,函数的参数数量是固定的,所以你不会是能写

(op) 1 2 

(op) 1 2 3 4 

对于任何给定的运营商都op。如果这是您想要的,您将需要使用列表或其他数据结构。如果你只是想避免命名变量,你总是可以做“1 + 2 + 3 + 4”。在F#中添加数字列表的最常用的方式是List.sum [1;2;3;4],这也避免了变量。