如何使“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
解释为一个函数,可以应用于文字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
前者表明,由于现在有一种将数字文字解释为函数的范围内方法,我们可以相当多地折叠所有以前的约束。后者按原样产生一个数字 "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
[((),[()])]
几年前,我遇到了 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
解释为一个函数,可以应用于文字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
前者表明,由于现在有一种将数字文字解释为函数的范围内方法,我们可以相当多地折叠所有以前的约束。后者按原样产生一个数字 "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
[((),[()])]