如何使“1 2 3”成为 Haskell REPL 环境中的有效表达式?

How to make "1 2 3" a valid expression in a Haskell REPL environment?

几年前,我遇到了 haskell.org 并使用了它的 REPL。我尝试的其中一个表达式只是一串数字,用空格分隔,比如 1 2 3 我很惊讶,因为它没有产生错误,但被评估并返回了其中的一些 Haskell 类型描述,顺便说一句,对于 C 和 JAVA 程序员来说似乎非常有趣。这可能只是一个细微差别,但结果确实让我感到好奇,因为一组孤立的参数本身似乎就是一个值。

有一个可以尝试的表达式示例:foldr (:) [] [1, 2, 3]。我只是尝试了 (:),它仍然是一个有效的表达式并返回了某种结构。

如今,同一站点的 REPL 无法识别这两个表达式。而且我还从 here 下载并安装了 Haskell 平台,它转到 GHCi REPL 也无法识别它。我试过这个:

:set -XFlexibleContexts

:set -XAllowAmbiguousTypes

正如 REPL 消息所建议的那样,但它没有用。

我知道这可能不是有用的行为,但我仍然想重现它。

提前谢谢你。

我怀疑你还记得这两种结果之一:

> :t 1 2 3
1 2 3 :: (Num (t1 -> t -> t2), Num t, Num t1) => t2
> 1 2 3

<interactive>:7:1: error:
    • No instance for (Num (t1 -> t0 -> a0)) arising from a use of ‘it’
        (maybe you haven't applied a function to enough arguments?)
    • In a stmt of an interactive GHCi command: print it

前者表明Haskell试图将文字1解释为一个函数,可以应用于文字23Num (t1 -> t -> t2) 约束表示 1 可以解释为双参数函数,而 Num tNum t1 约束表示 23 可以解释为该函数的合适参数。

后者表示同样的事情,但继续说它找不到这样的实例来说明如何将数字解释为函数。

喜欢的可以加一个;你至少需要这样的东西:

instance Num b => Num (a -> b) where fromInteger = pure . fromInteger

(这使其他 Num 方法未定义,这意味着如果您尝试在函数类型中使用它们,它们将抛出错误。)

根据该声明,上述两个查询的结果略有不同:

> :t 1 2 3
1 2 3 :: Num t => t
> 1 2 3
1

前者表明,由于现在有一种将数字文字解释为函数的范围内方法,我们可以相当多地折叠所有以前的约束。后者按原样产生一个数字 "by accident":单态限制将多态类型 Num t => t 默认为 Integer 并打印结果。

(:) 的情况类似,我想:您可能记得问过一个 :t 查询,它工作得很好:

> :t (:)
(:) :: a -> [a] -> [a]

虽然没有内置打印功能的标准方法,因此尝试 "run" (:) 本身会产生错误:

> (:)

<interactive>:14:1: error:
    • No instance for (Show (a0 -> [a0] -> [a0]))
        arising from a use of ‘print’
        (maybe you haven't applied a function to enough arguments?)
    • In a stmt of an interactive GHCi command: print it

这个错误基本上说明了我所做的:默认情况下无法显示函数。和以前一样,您可以根据需要添加一个;一个流行但有损的是:

> :m + Text.Show.Functions
> (:)
<function>

这样做会稍微减少损耗(不是另外!):

> :m + Data.Typeable
> instance (Typeable a, Typeable b) => Show (a -> b) where show = show . typeOf

...但您不能将它直接应用于 (:),因为它仅适用于单态函数。

> (:) 3
[Integer] -> [Integer]

当然,最好的办法是使用 lossless show implementation,但它对可以与哪些函数一起使用的限制更为严格:仅限具有有限域的单态函数(如前所述)(新限制)。

> :m + Data.Universe.Instances.Reverse
> enumFrom
[((),[()])]