我正在努力使用F#类型的签名表示法.例如,假设您有折叠功能:
let rec Fold combine acc l =
...
Run Code Online (Sandbox Code Playgroud)
可能有这种类型的签名:
('a -> 'b -> 'a) -> 'a -> list<'b> -> 'a
Run Code Online (Sandbox Code Playgroud)
我会读到的
一个有三个参数的函数:
并返回'a.
但是,对于我的穴居人大脑来说,将其表达为更有意义
('a, 'b -> 'a), 'a, list<'b> -> 'a
Run Code Online (Sandbox Code Playgroud)
我确定有一个语义原因,为什么参数用箭头与函数返回类型完全相同,但不知何故我错过了它,并且到目前为止在书籍/文章中没有找到明确的解释.每当我看到类型签名时,我都要花很多时间来理解它.我觉得我只是错过了让"解密"显而易见的那一小块难题.
有人可以赐教吗?
Jul*_*iet 15
我确定有一个语义原因,为什么参数用箭头与函数返回类型完全相同,但不知何故我错过了它,并且到目前为止在书籍/文章中没有找到明确的解释.
你正在阅读第一个功能是正确的.对于即时解密,类型签名表示如下:
val functionName = inputType1 -> inputType2 -> ... -> inputTypeN -> returnType
Run Code Online (Sandbox Code Playgroud)
通常,箭头符号表示功能是可以进行的.
// val add4 : int -> int -> int -> int -> int
let add4 a b c d = a + b + c + d;;
// val f : (int -> int)
let f = add4 1 2 3 // returns (int -> int) waiting for last argument
Run Code Online (Sandbox Code Playgroud)
因为函数是curry,你可以在技术上写这样:
// val add4 : int -> int -> int -> int -> int
let add4 = (fun a -> (fun b -> (fun c -> (fun d -> a + b + c + d))));;
// val f : (int -> int)
let f = fun x -> add4 1 2 3 x
Run Code Online (Sandbox Code Playgroud)
如果你考虑一下,add4签名就相当于:
val add4 : int -> (int -> (int -> (int -> int) ) )
Run Code Online (Sandbox Code Playgroud)
我相信我们使用箭头符号,因为当我们明确地讨论如上所示的参数时,它类似于函数的结构.
签名是以这种方式编写的,因为所谓的Currying.稍微更准确的描述函数的方法是它接受一个(函数接受a 'a并将函数从a 返回'b到a 'a)并返回一个函数,该函数接受a 'a并将函数从a返回list<'b>到a 'a.因此,类型签名可以重写为
('a -> 'b -> 'a) -> ('a -> (list<'b> -> 'a))
Run Code Online (Sandbox Code Playgroud)
您可以在F#中编写一个类似的函数,其类型与您提议的类似(但在F#中它将被写为('a * 'b -> 'a) * 'a * list<'b> -> 'a.但是,现有函数的优点是通过仅提供前缀可以很容易地部分应用它.参数.例如:
let sum = List.fold (+) 0
Run Code Online (Sandbox Code Playgroud)
使用你的定义,你必须写
let sum l = List.fold((fun (x,y) -> x + y), 0, l)
Run Code Online (Sandbox Code Playgroud)