如何制作" 1 2 3" Haskell REPL环境中的有效表达式?

时间:2018-02-06 01:49:25

标签: haskell types read-eval-print-loop expression-evaluation

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

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

现在,同一个网站的REPL并没有认识到这两个表达方式。我还从here下载并安装了Haskell平台,并且GHCi REPL也没有识别它。我试过这个:

:set -XFlexibleContexts

:set -XAllowAmbiguousTypes

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

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

提前谢谢你。

1 个答案:

答案 0 :(得分:8)

我怀疑你记得这两个结果中的一个:

> :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解释为可应用于文字23的函数; Num (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

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

(:)的故事是相似的,我希望:您可能还记得问过:t查询,这很好用:

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

但是,没有内置打印功能的标准方法,因此尝试单独“运行”(:)会产生错误:

> (:)

<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
[((),[()])]