【发布时间】:2020-03-08 07:46:19
【问题描述】:
我正在阅读 Scott Wlaschin 的优秀文章 Understanding map and apply 并运行一些 Haskell 代码来理解这些概念(Functor、Applicative、...)。我偶然发现了一个我不理解的行为。
为什么评估pure add1 什么也不打印?评估表达式的值是多少?为什么pure add1 "abc" 把函数add1 还给我?
我知道pure 将一个价值提升到提升的世界(在文章中如此称呼)。由于我没有在某处提供具体的提升值或足够的类型信息,因此类型约束是通用的并且保持Applicative f。因此我了解pure add1 的类型。但这里发生的其他事情让我无法理解。
$ stack ghci
GHCi, version 8.8.2
λ: add1 :: Int -> Int ; add1 x = x + 1
λ: :t add1
add1 :: Int -> Int
λ: add1 100
101
λ: :t pure
pure :: Applicative f => a -> f a
λ: pure add1
λ: :t pure add1
pure add1 :: Applicative f => f (Int -> Int)
λ: pure add1 "abc"
<interactive>:8:1: error:
• No instance for (Show (Int -> Int)) 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
λ: :t pure add1 "abc"
pure add1 "abc" :: Int -> Int
λ: pure add1 "abc" 100
101
编辑 我认为@chi 的两个 cmets 和 @sarah 的答案回答了这个问题,因为它显示了 GHCi 选择的应用程序来评估表达式并解释了观察到的行为。
【问题讨论】:
-
看起来和ghci special case for Applicative?是同一个问题,但它让我无法理解
pure add1 "abc"。 -
不,我认为这是一个不同的问题:如果它是相同的,您将拥有
pure add1 :: IO (Int -> Int),这不允许您使用pure add1 "abc" 100。但我必须说,这种行为看起来非常奇怪——我当然不知道如何解释它。 -
IO 在 GHCi 中接受特殊处理。您的
pure add1被视为IO (Int -> Int)类型的值,因此它会运行(无效)。然后不打印其最终结果 (add1),因为它不是Showable。相比之下,尝试pure "hello",它是一个IO String,它的值在最后打印出来。 -
@chi 如果这是真的,
pure add1 "abc"不会进行类型检查。除了隐含的print it,问题中没有代码涉及IO。看我的回答 -
@sara 当您在 GHCi 中输入
pure add1时,它会在 IO 中进行解释。当您输入pure add1 something时,这将在(->) a应用程序中进行解释。 GHCi 的魔力会尽可能在顶层使用 IO:前者是,后者不是。
标签: haskell ghci applicative