几年前,我遇到了haskell.org并且使用了它的REPL。我试过的其中一个表达式只是一个数字序列,用空格分隔,比如1 2 3
,我感到很惊讶,因为它没有产生错误,但是被评估并返回了一些Haskell类型描述,顺便说一句,C和JAVA程序员似乎非常有趣。它可能只是一个细微差别,但结果确实让我感到好奇,因为一组孤立的参数似乎本身就是一个价值。
有一个表达式可以尝试:foldr (:) [] [1, 2, 3]
。我只尝试了(:)
,它仍然是一个有效的表达式并返回了某种结构。
现在,同一个网站的REPL并没有认识到这两个表达方式。我还从here下载并安装了Haskell平台,并且GHCi REPL也没有识别它。我试过这个:
:set -XFlexibleContexts
和
:set -XAllowAmbiguousTypes
正如REPL消息所建议的那样,但它没有用。
我知道这可能不是一种有用的行为,但我仍然希望重现它。
提前谢谢你。
答案 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
解释为可应用于文字2
和3
的函数; Num (t1 -> t -> t2)
约束表明1
可以解释为双参数函数,而Num t
和Num t1
约束表示2
和3
可以解释为此函数的合适参数。
后者表示同样的事情,但接着说它还找不到这样一个实例来讲述如何将数字解释为函数。
如果您愿意,可以添加一个;你需要的最少是这样的:
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 => t
为Integer
并打印结果。
(:)
的故事是相似的,我希望:您可能还记得问过: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
[((),[()])]