Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print type of polymorphic function (or value) in ghci with type defaulting rules applied?

When I enter :t command in GHCi I see polymorphic type:

ghci> :t 42
42 :: Num t => t
ghci> :t div
div :: Integral a => a -> a -> a

But after I actually evaluate such functions I see result of type defaulting rules. Is there some command or ability to observe in ghci how type will be changed after type defaulting rules applied according to Haskell report and/or ghc implementation?

like image 398
Shersh Avatar asked Sep 13 '17 09:09

Shersh


3 Answers

You can do this by turning on the monomorphism restriction and then binding it to a new name:

Prelude> :set -XMonomorphismRestriction 
Prelude> let n = 42
Prelude> :t n
n :: Integer
Prelude> let p = (^)
Prelude> :t p
p :: Integer -> Integer -> Integer
Prelude> let e = (**)
Prelude> :t e
e :: Double -> Double -> Double
Prelude> let d = div
Prelude> :t d
d :: Integer -> Integer -> Integer

If you don't fancy the need to always define a new variable, you can get around this by using

Prelude> :def monotype (\e -> return $ ":set -XMonomorphismRestriction\nlet defaulted = "++e++"\n:t defaulted")

(you may want to put that in your .ghci file to always have the command available) and then

Prelude> :monotype (^)
defaulted :: Integer -> Integer -> Integer

Of course, the hidden global side-effect of enabling the monomorphism restriction is extremely ugly, but oh well...

like image 162
leftaroundabout Avatar answered Oct 14 '22 10:10

leftaroundabout


Since GHC 8.4.1 it's possible to use :type +d (or :t +d for short) option to print the type of an expression, defaulting type variables if possible.

ghci> :t 42
42 :: Num p => p
ghci> :t +d 42
42 :: Integer
ghci> :t div
div :: Integral a => a -> a -> a
ghci> :t +d div
div :: Integer -> Integer -> Integer
like image 3
Shersh Avatar answered Oct 14 '22 09:10

Shersh


Not a perfect solution, but it could be a first step.

> import Data.Typeable
> let withType x = (x, typeOf x)
> withType []
([],[()])
> withType 56
(56,Integer)

Note that, since the type a gets changed into (a,TypeRep), GHCi will not use all its defaulting magic. Still, some of it can be shown.

GHCi's :set +t option is also interesting, but prints the polymorphic type before the GHCi defaulting, it seems.

like image 4
chi Avatar answered Oct 14 '22 09:10

chi