类型推断(>>)(>>)(函数组合)

时间:2014-05-03 18:42:50

标签: f# type-inference

我已经在某个地方看到了(抱歉,我无法找到参考资料)这个运算符组合:

(>>)(>>)

其中(>>): (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) - (>>)the function composition operator

我发现更简单的例子很容易理解。例如(>>)f,其中f: i -> i(>>)(i -> i)变为(i -> 't) -> i -> 't。这是因为('a -> 'b)被剔除,'b被推断为i't仍为通用类型。

我不完全理解(>>)(>>)

使用

(>>)(>>)(<<)(<<)会用于什么?

为什么有必要使参数明确化?

> (>>)(>>);;

  (>>)(>>);;
  -^^^^^^

C:\Users\...\Temp\stdin(3,2): error FS0030: Value restriction. The value 'it' has been inferred to have generic type
    val it : (((('_a -> '_b) -> '_c -> '_b) -> '_d) -> ('_c -> '_a) -> '_d)    
Either make the arguments to 'it' explicit or, if you do not intend for it to be generic, add a type annotation.

根据错误消息的建议:

> let strangeFun arg = (>>)(>>) arg;;

val strangeFun : arg:((('a -> 'b) -> 'c -> 'b) -> 'd) -> (('c -> 'a) -> 'd)

1 个答案:

答案 0 :(得分:1)

过去,有一些关于价值限制的解释; here是我写的,解释了为什么有必要。为了完整起见,我将在此复制示例代码,如果删除了值限制,则该代码将不正确:

let f : 'a -> 'a option =
    let r = ref None
    fun x ->
        let old = !r
        r := Some x
        old

f 3           // r := Some 3; returns None : int option
f "t"         // r := Some "t"; returns Some 3 : string option!!!

至于(>>)(>>)将用于什么,我承认我不知道。然而,有一个看起来相似但有用的函数,它是(<<) << (<<)(在Haskell中更为人所知的(.).(.)),它返回一个类似的合成运算符,其第二个和返回的函数可以取 2 参数而不是一个。

let (<<<<) f = ((<<) << (<<)) f;;

// val ( <<<< ) : f:('a -> 'b) -> (('c -> 'd -> 'a) -> 'c -> 'd -> 'b)