为什么F#“Generic-izing”是我的歧视联盟

时间:2014-01-13 17:00:26

标签: f# type-inference

我写了我认为非常直接的F#代码,但编译器似乎在类型推断上绊倒。它不是从受歧视的联盟中推断出来,而是通过推断。但是,我不明白为什么,因为我的代码不允许进行通用推理。

以下是代码:

module Log

open System

type LogInput =
    | Message of (int * string)
    | Error of Exception
    | Process of ( string * unit -> int )

let log i =
    match i with
    | Message( indent, str ) ->
        str
        |> printfn "Message () %s%s" ( String.replicate ( indent * 4 ) " " )
    | Error( err ) ->
        err.ToString()
        |> printfn "Error () %s" 
    | Process( name, f ) ->
        printfn "Beginning %s..." name
        printfn "Completed %s\nReturn Code: %i" name <| f()

编译器正确推断indentstrerr的类型,但想推断'a'b namef(根据受歧视的联盟或用法,这是没有意义的)。发生了什么事?

错误消息:

Log.fs(18,16): error FS0001: This expression was expected to have type
    string * unit -> int    
but here has type
    'a * 'b    

1 个答案:

答案 0 :(得分:3)

哎呀......弄清楚了。

我错误地定义了这种类型。我的意思是接受一个字符串和一个函数接受单元并返回int。相反,我定义了一个函数,它接受一个字符串和单元并返回int。以下是我在歧视联盟中纠正定义的方法:

type LogInput =
    | Message of (int * string)
    | Error of Exception
    | Process of ( string * ( unit -> int ) )

混淆运算符优先级的经典案例。请点击此处了解更多信息:

Symbol and Operator Reference (F#)

*的优先级高于->,因此stringunit的元组胜过函数unit -> int的定义