消失的应用程序?

Disappearing applicative?

在未指定 Applicative 实例的情况下,我对 pure 的行为有点困惑。在此示例中,我希望结果值为应用上下文中的数字 5:

Prelude> pure 5 :: Applicative t => t Integer
5
Prelude> :t it
it :: Integer

相反,它只是一个普通的整数。

如果指定了应用实例,如下例所示,返回值是应用类型,如我所料:

Prelude> pure 5 :: Maybe Integer
Just 5
Prelude> :t it
it :: Maybe Integer

为什么 Applicative t 在第一个示例中似乎消失了?

似乎正在剥离未指定的应用上下文以进行最终评估以打印到输出,但我想知道这方面的规则是什么。

这是简要讨论过的 GHCi 特性 here。当在 GHCi 提示符下输入表达式并求值时,如果它的类型可以与 IO a 统一,那么它将作为一个 IO 动作执行 return 类型 a,并且 return 将显示操作的值(如果它不是 () 并且它有一个 Show 实例)。

原来it对应的值会被设置为IO action的return值,而不是IO action本身。我想这个想法是,如果你要写:

> getLine
I typed this!    <-- what I typed
"I typed this!"  <-- the return value displayed

您希望 it 给出 returned 值,而不是 re-run IO 操作:

> it
"I typed this!"
> :t it
it :: String

具体来说,在您的情况下,表达式的类型:

> pure 5 :: Applicative t => t Integer

可以和IO Integer统一,原来如此。 IO 操作是 运行,return 值是 5,它成为 it.

的输出和值

注意如果你写了一个不能与 IO 统一的表达式会发生什么:

> pure 5 :: (Applicative t, Foldable t) => t Integer
[5]

这里,因为IO在范围内没有Foldable实例,类型不能与IO统一,取而代之的是GHCi的“扩展默认”规则,用于将类型分配给未指定的使用类型变量。这些扩展规则包括对未知类型 * -> * 使用列表类型 [],因此我们得到 pure 5 :: [Integer]。如果我们首先添加一个 Foldable IO 实例,然后与 IO 的统一再次起作用,我们得到您已经观察到的行为:

> instance Foldable IO   -- this works, despite the warning

<interactive>:11:10: warning: [-Wmissing-methods]
    • No explicit implementation for
        either ‘foldMap’ or ‘foldr’
    • In the instance declaration for ‘Foldable IO’
> pure 5 :: (Applicative m, Foldable m) => m Integer
5