为什么F#推断我的函数实现了IComparable?

时间:2012-04-29 03:37:42

标签: f# type-inference

我是一个业余爱好者程序员(通过贸易做饭),目前正在尝试自学F#和函数式编程。

无论如何,我正在和DeflateStream一起玩弄并写下以下两个函数:

let Compress compressMe =
    let ds = new DeflateStream(File.Create("compressed.txt"), CompressionMode.Compress)
    File.OpenRead(compressMe).CopyTo(ds)
    ds.Close()

let Decompress =
    let ds = new DeflateStream(File.OpenRead("compressed.txt"), CompressionMode.Decompress)
    ds.CopyTo(File.Create("decompressed.txt"))
    ds.Close()

在主要功能的主体中,它们一个接一个地被称为:

Compress args.[0]
Decompress

但是,如果在运行程序时{(1}}}不存在,则Decompress会抛出FileNotFoundException,这是令人惊讶的,因为唯一可以抛出此内容的是调用File.OpenRead("compress.txt") 。大约一个小时后,我发现Decompress正在实施IComparable,并且在主函数调用它之前正在执行。我发现通过将其定义更改为let Decompress () = [...],它不再实现IComparable并且我的代码按照预期执行。任何人都可以告诉我为什么F#推断IComparable以及为什么这样和推断会导致函数在标有[<EntryPoint>]的主函数之前执行?另外,请原谅我的代码的不完美风格,我在这方面非常新。

谢谢你。

3 个答案:

答案 0 :(得分:4)

我不完全确定IComparable位,但问题是如果没有括号,编译器会将Decompress视为而不是函数。这与你写过的内容类似。

let compressedName = "compressed.txt"

在这种情况下,compressedName现在是一个值。添加括号告诉编译器这是一个函数,每次函数时都必须调用它的代码,而不是由你编写的代码初始化一次(在入口点之前)的值。

答案 1 :(得分:4)

当你写

之类的东西时
let value = 
    //some long calculation
[<Entrypoint>]
let main args = ...

编译器在main之前执行长计算。这是因为您可能稍后在代码中使用该值。要取消此操作,您需要使用let value() = ...

我不确定Icomparable的来源,但这是发生事情的关键。

注意,如果你写

let a = ...
let b = ...

编译器将在a执行之前计算保证b

答案 2 :(得分:0)

正如其他人所指出的那样,声明中没有括号是很重要的。

let Decompres = ...

声明类型为unit的变量。此类型用于表示“数据”(即使此数据不编码很多信息),它实现IComparable,就像任何其他面向数据的类型一样。

let Decompress() = ...

声明一个函数,并且F#中的函数不具有可比性,可能是因为函数上没有普遍接受的相等概念。

我看不出Decompress的“IC Comparable-ness”与您获得的例外情况有关。