我写了我认为非常直接的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()
编译器正确推断indent
,str
和err
的类型,但想推断'a
和'b
name
和f
(根据受歧视的联盟或用法,这是没有意义的)。发生了什么事?
错误消息:
Log.fs(18,16): error FS0001: This expression was expected to have type
string * unit -> int
but here has type
'a * 'b
答案 0 :(得分:3)
哎呀......弄清楚了。
我错误地定义了这种类型。我的意思是接受一个字符串和一个函数接受单元并返回int。相反,我定义了一个函数,它接受一个字符串和单元并返回int。以下是我在歧视联盟中纠正定义的方法:
type LogInput =
| Message of (int * string)
| Error of Exception
| Process of ( string * ( unit -> int ) )
混淆运算符优先级的经典案例。请点击此处了解更多信息:
Symbol and Operator Reference (F#)
*
的优先级高于->
,因此string
和unit
的元组胜过函数unit -> int
的定义