【问题标题】:Types and functions类型和功能
【发布时间】:2012-02-26 02:01:46
【问题描述】:

考虑以下几点:

type T () =
  member x.y = 4

let a =
  let fn () (k: T) = ()
  fn ()

let b =
  let fn () (k: System.IO.Directory) = ()
  fn ()

a 失败,而 b 正常。错误信息是:

值 'a' 已被推断为具有泛型类型 val a : ('_a -> unit) when '_a :> T是通用的,添加类型注释

为什么以及如何解决这个问题?

【问题讨论】:

    标签: function types f#


    【解决方案1】:

    错误消息本身会告诉您需要做什么——添加类型注释:

    let a : T -> unit = 
      let fn () (k: T) = () 
      fn () 
    

    您首先看到错误的原因是编译器试图概括a 的定义(请参阅规范的this part),这导致您在错误消息中看到奇怪的签名.

    b不需要这样做的原因是System.IO.Directory是密封的,所以不需要一概而论。

    【讨论】:

      【解决方案2】:

      您面临值限制,因为a 看起来像一个常量,但它返回一个函数。 看看这个问题:

      Understanding F# Value Restriction Errors

      解决它的一个简单方法是在a 的定义中添加一个变量。

      let a x =
        let fn () (k: T) = ()
        fn () x
      

      我不知道为什么它适用于某些类型, b 就是这种情况

      【讨论】:

      【解决方案3】:

      如果 T 在哪里记录而不是类,它会起作用。但是由于某种原因,如果 T 是一个类,则必须为编译器拼写出来,

      type T () =
        member x.y = 4
      
      let a<'U when 'U :> T> =
        let fn () (k: 'U) = ()
        fn ()
      
      let test0 = a<T> (T())  // You can be explicit about T,
      let test1 = a (T())     // but you don't have to be.
      

      编辑:所以我玩得更多,奇怪的是,编译器似乎满足于任何类型限制:

      type T () =
        member x.y = 4
      
      type S () =
        member x.z = 4.5
      
      let a<'U when 'U :> S> =
        let fn () (k: T) = ()
        fn ()
      
      let test = a (T())     // Is OK
      let test = a<T> (T())  // Error: The type 'T' is not compatible with the type 'S'
      

      类型 S 与上面代码中的任何内容都没有任何关系,但编译器仍然乐于有任何类型的限制。

      【讨论】:

        猜你喜欢
        • 2019-12-28
        • 2018-05-01
        • 1970-01-01
        • 2020-08-03
        • 1970-01-01
        • 2016-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多