"let definition is a constant" 提示背后的动机是什么?

What is the motivation behind the "let definition is a constant" hint?

启用 -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 

这个提示试图"hint"反对什么?


如果我在行 (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 的有效用法。提示是否另有暗示?

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

因此 "hint against" 的概念是错误的。你也不应该努力使你的代码 "hints free".

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

I, the compiler, use to move type annotated constants like your 'name' to the top level, because it is safe to do so and may eliminate some or all nested levels of let. This will also speed up things later in type checking, code generation and run time. In addition, you might consider to do the same yourself, lest you end up defining the same constant over and over in different let expressions or where clauses.

请注意,在

foo :: Int
foo = 42

我们正在注释 foo,而在

foo = 42 :: Int

我们只注释右侧,因此从技术上讲,foo 没有注释,必须进行类型推断。这就是看似不合理和令人困惑的差异的来源。