"定义是一个常数"背后的动机是什么?暗示?

时间:2018-02-21 00:20:48

标签: frege

如果启用-hints选项,编译器将针对以下程序发出提示消息:

module Main where

main :: IO ()
main = do
    let magic :: Int  -- (A)
        magic = 123
    println magic

$ fregec -hints Main.fr
H Main.fr:5: let definition is a constant: magic
calling: javac -cp /home/yohashi/lib/java/fregec.jar:. -d . -sourcepath . -encoding UTF-8 ./Main.java 

这个提示尝试了什么"提示"针对吗

如果我在行(A)上省略了类型注释(对不正确的术语而言),那么提示就会消失:

main = do
    let magic = 123
    ...

类型归属没有提示:

main = do
    let magic = 123 :: Int

同样的事情发生在where声明中:

main = println magic
  where
  magic :: Int
  magic = 123                     -- let definition is a constant: magic
  magica = 123                    -- no hint
  magicb = 123 :: Int             -- no hint
  magicfun :: Int -> Int
  magicfun = succ                 -- let definition is a constant: magicfun
  magicfuna = succ                -- no hint
  magicfunb = succ :: Int -> Int  -- no hint
  magicfunc :: Int -> Int
  magicfunc i = succ i            -- no hint

magicfun的提示特别令人讨厌,因为它不鼓励无点符号(与magicfunc相比)。

所以我的问题是:这个提示背后的动机是什么? 我认为为简单或复杂的表达式赋予别名是let / where的有效用法。提示暗示不是吗?

1 个答案:

答案 0 :(得分:1)

你是对的,缩写函数的常量或别名是完全正常的。但是,提示不是警告,而只是关于你的程序的评论,可能会或可能不会告诉你一些你还不知道的事情。

因此,“提示反对”的概念是错误的。你也不应该努力使你的代码“免费提示”。

具有讽刺意味的是,看起来有问题的提示需要另外一些提示来解释它。它应该是:

  

我,编译器,用于将类型注释常量(如“ name ”)移动到顶层,因为这样做是安全的,并且可能会消除一些或所有嵌套级别的let。这也将在以后的类型检查,代码生成和运行时加快速度。另外,您可能会考虑自己做同样的事情,以免最终在不同的let表达式或where子句中反复定义相同的常量。

请注意,

foo :: Int
foo = 42

我们正在注释foo,而在

foo = 42 :: Int

我们仅对右侧进行注释,因此从技术上讲,foo没有注释,必须进行类型推断。所以这就是看似不合理和混乱的差异所在。