How does GHCi print partially-applied values created from “pure”?

ⅰ亾dé卋堺 提交于 2020-01-14 09:32:21

问题


I've been playing around with Applicative instances in order to figure out how they work. However, I honestly don't understand this behavior.

If I define my own datatype, then apply pure to it with no other arguments, nothing prints out, but it errors if I try to apply something to the result.

ghci> data T = A
ghci> pure A
ghci> pure A 0

<interactive>:21:1:
    No instance for (Show T) arising from a use of ‘print’
    In a stmt of an interactive GHCi command: print it

However, if I make T an instance of Show, then A is printed out in both cases.

ghci> data T = A deriving (Show)
ghci> pure A
A
ghci> pure A 0
A

What I really don't understand is how pure A can be a value that is printed differently between the two cases. Isn't pure A partially applied?

I do understand why calling pure A 0 errors in the first example and doesn't in the second—that makes sense to me. That's using the ((->) r) instance of Applicative, so it simply yields a function that always returns A.

But how is pure instantiated with only one value when the type of the applicative itself isn't yet known? Furthermore, how can GHC possibly print this value?


回答1:


GHCi is a little bit peculiar. In particular, when you type an expression at the prompt, it tries to interpret it in two different ways, in order:

  1. As an IO action to execute.
  2. As a value to print out.

Since IO is Applicative, it is interpreting pure A as an IO action producing something of type T. It executes that action (which does nothing), and since the result is not in Show, it does not print anything out. If you make T an instance of Show, then it kindly prints out the result for you.

When you write pure A 0, GHCi sees this:

pure :: Applicative f => a -> f a
pure A :: Applicative f => f T

And since you apply pure A to 0, pure A must be a function a->b for some types a and b, and a must contain 0.

(Num a, Applicative f) => f T ~ (a -> b)

(Note that x ~ y means that x and y unify—they can be made to have the same type.)

Thus we must have f ~ ((->) a) and T ~ b, so in fact GHC infers that, in this context,

pure A :: Num a => ((->) a) T

Which we can rewrite as

pure A :: Num a => a -> T

Well, (->) a is an instance of Applicative, namely "reader", so this is okay. When we apply pure A to 0 we get something of type T, namely A. This cannot be interpreted as an IO action, of course, so if T is not an instance of Show, GHCi will complain.




回答2:


When you give a value of ambiguous type to the GHCi prompt to evaluate, it tries to default the type in various ways. In particular, it tries whether it can fit an IO a type, in case you want to execute an IO action (see the GHC manual). In your case, pure A defaults to the type IO T. Also:

Furthermore, GHCi will print the result of the I/O action if (and only if):

  • The result type is an instance of Show.
  • The result type is not ().


来源:https://stackoverflow.com/questions/28978857/how-does-ghci-print-partially-applied-values-created-from-pure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!