我注意到在SML中有两种定义函数的方法。例如,如果你使用add函数,这有两种方式:
import actions from './actions'
const reducer = (state = {}, action) => {
if (actions[action.type]) return Object.assign({},
state, actions[action.type](action)
);
return state;
}
第一种方法将函数类型创建为:
fun add x y = x+y;
fun add(x,y) = x+y;
第二个创建函数类型:
val add = fn : int -> int -> int
同一功能的这两种类型有什么区别?还有为什么同一个函数有两种类型?
答案 0 :(得分:5)
如果我们从你的两个定义中删除语法糖,它们就变成了:
val add = fn x => fn y => x+y
和
val add = fn xy =>
case xy of
(x,y) => x+y
因此,在第一种情况下,add
是一个接受参数x
并返回另一个函数的函数,该函数接受参数y
然后返回x+y
。这种通过返回另一个函数来模拟多个参数的技术称为currying。
在第二种情况下,add
是一个函数,它将一个元组作为参数,然后添加元组的两个元素。
这也解释了两种不同的类型。 ->
是功能箭头,它与右侧相关联,这意味着int -> int -> int
与描述采用int -> (int -> int)
并返回int
的函数的int -> int
相同功能
*
是用于元组类型的语法,即int * int
是包含两个整数的元组类型,因此int * int -> int
(括号为{{1}因为(int * int) -> int
的优先级高于*
,所以它描述了一个带有两个整数元组并返回一个int的函数。
答案 1 :(得分:0)
这两个函数不同的原因是Currying
的现象。具体来说,Currying是使用dom(f) = R^{n}
编写任何函数的功能,该函数从R
n
- 次获取输入。这基本上是通过确保每个输入返回下一个要接受的变量的函数来实现的。这就是->
符号所代表的含义 - 它是Curry-Howard Isomorphism
的基本结果。所以:
fun addCurry x y = x + y (* int -> int -> int *)
fun addProd (x,y) = x + y (* (int*int) -> int *)
告诉我们addCurry
是将addProd
缩减为可用于替代"的形式。并返回变量。因此,addProd
和addCurry
在上下文中是等效的。但是,它们不在语义上等效。
(int*int)
是产品类型。它表示它预计会input1=int
和input2=int
。 int -> int
表示需要int
并返回int
。它是箭头型。
如果您有兴趣,您可能还想知道SML函数只有两种参数:
1)咖喱
2)元组 - 因此,fun addProd (x,y)
表示(x,y)
作为函数参数的元组。