Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What type is chosen for a polymorphic expression when printed?

Tags:

haskell

ghci

What is the type of return "abc" when printed in ghci?

The point of the question is that it's polymorphic in the monad:

ghci> :t return "abc"
return "abc" :: (Monad m) => m [Char]

and what gets printed depends on which monad is chosen:

ghci> return "abc" :: Maybe String
Just "abc"

ghci> return "abc" :: [] String
["abc"]

but here's what's actually printed:

ghci> return "abc"
"abc"
like image 259
Matt Fenwick Avatar asked Aug 13 '12 16:08

Matt Fenwick


People also ask

What is a polymorphic data type?

A function that can evaluate to or be applied to values of different types is known as a polymorphic function. A data type that can appear to be of a generalized type (e.g. a list with elements of arbitrary type) is designated polymorphic data type like the generalized type from which such specializations are made.

What are the three types of polymorphism?

In Object-Oriented programming languages there are three types of polymorphism: subtype polymorphism, parametric polymorphism, and ad-hoc polymorphism.

In which type of polymorphism a name denotes?

Three branches of polymorphism In object-oriented programming, this is often called generic programming. Inclusion polymorphism, also known as subtyping, is when a single name refers to many instances of different classes as long as they share the same superclass.

In which type of polymorphism a function denotes different and potentially?

In programming languages, ad hoc polymorphism is a kind of polymorphism in which polymorphic functions can be applied to arguments of different types, because a polymorphic function can denote a number of distinct and potentially heterogeneous implementations depending on the type of argument(s) to which it is applied.


2 Answers

When you type an expression expr into GHCi, the following things happen:

  • The expression is type-checked. If there is an error, GHCi tells you the error and gives up.
  • Otherwise, say expr is found to have type t; GHC tries to match t against IO a.
  • If it succeeds, then it executes something like it <- expr, then if a is an instance of Show and is not (), it executes print it.
  • If it fails, and t itself is an instance of Show, GHCi does something like let it = expr and then print it.
  • Otherwise, it complains.

Essentially, you need a way at the GHCi prompt both of running IO actions and getting at the values they return, and of playing around with pure values and seeing what you get. That's why GHCi behaves the way it does: if it seems like you're using an IO action, GHCi will do it, and then if that action has a result that can be shown and is interesting (i.e. not ()) then it shows the result to you. If it can't show the result to you, then it's no big deal, because you probably just wanted to run the IO action anyway; if you wanted the result you would have named it with <-. On the other hand, if it seems like your expression is not an IO action, GHCi calculates it and shows it to you, and if it can't be shown then GHCi can't do anything useful (no side-effects this time), so complains.

In this case, return "abc" typechecks as IO String, and String is an instance of Show, so GHCi does something like

it <- return "abc"
print it

which by the monad laws is exactly the same as just doing

print "abc"

hence the result.

like image 54
Ben Millwood Avatar answered Nov 15 '22 09:11

Ben Millwood


Haskell has a slightly baffling set of rules for deciding the types of expressions involving numbers; you can see the Report section on ambiguous types and default instances. So the answer to the general question is complicated. But within GHCi, if you enter an expression e, you can rely on these rules to apply:

  • If the expression e can be typed as IO T for some type T, and if T has a Show instance, GHCi will run the computation and print the resulting value of type T. That's what's happening in your third example.

  • If the expression e *cannot* be typed in the IO monad, then the default-instance rules come into play, and GHCi will choose a type according to those rules. If the type has a Show instance GHCi will then print show e. That's what happens in your first two examples: Maybe String and [String] are pure values with Show instances.

    If e's type does not have a Show instance, then GHCi will complain. That will happen if you type an expression like flip take.

like image 20
Norman Ramsey Avatar answered Nov 15 '22 09:11

Norman Ramsey