Reading haskell book about types I want to repeat sample for :t command:
ghci> :t 'a'
'a' :: Char
ghci> :t True
True :: Bool
ghci> :t "HELLO!"
"HELLO!" :: [Char]
ghci> :t (True, 'a')
(True, 'a') :: (Bool, Char)
ghci> :t 4 == 5
4 == 5 :: Bool
Unfortunately I can't install haskell locally, thatswhy I use ideone.com
But I can't understand how create the same sample.
I tried like this:
main = do
putStrLn "Start"
:t 'a'
putStrLn "Finish"
or this:
:t 'a'
or:
putStrLn ("Finish" ++ show :t 'a')
Is there a possibility to show types without installing ghci? Maybe, there is another web fiddle that can do this?
You can use typeOf :: forall a. Typeable a => a -> TypeRep to obtain the TypeRep object. It requires that your type is Typeable, but with the given examples that is the case.
For example:
import Data.Typeable(typeOf)
main = putStrLn ("Finish" ++ show (typeOf 'a'))
This will not print full polymorphic types, since at compile time the types are determined. You thus see the type as is derived by the Haskell compiler.
Related
I am reading the excellent article Understanding map and apply by Scott Wlaschin and running some Haskell code to understand the concepts (Functor, Applicative, ...). I stumbled upon a behaviour I do not understand.
Why evaluating pure add1 prints nothing ? What is the value of the evaluated expression ? Why pure add1 "abc" gives me back the function add1 ?
I understand that pure lifts a value into the elevated world (so called in the article). Since I do not provide a concrete lifted value somewhere or enough type information, the type constraint is general and stays Applicative f. Thus I understand the type of pure add1. But the rest of what's happening here eludes me.
$ 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
EDIT
I think the two comments by #chi and the answer by #sarah answers the question because it shows the applicative chosen by GHCi to evaluate the expression and that explains the observed behaviour.
Since you are applying the expression pure add1 to the value "abc", the Applicative instance gets picked to be the one for (->) String. In that instance, pure = const, so your final expression is const add1 "abc" which is add1, which has no Show instance!
I tried to check this stackoverflow answer with ghci and get the following error:
> import Data.List
> let m = head . sort
> m [2,3,4]
<interactive>:5:4:
No instance for (Num ()) arising from the literal `2'
Possible fix: add an instance declaration for (Num ())
In the expression: 2
In the first argument of `m', namely `[2, 3, 4]'
In the expression: m [2, 3, 4]
Unfortunately I cannot reproduce the error in a written haskell file:
-- file.hs
import Data.List
main = do
let m = head . sort
putStrLn $ show $ m [2,3,4]
Running this file with runhaskell file.hs gives me the expected value 2. What is my mistake in the ghci session?
Edit: I noted, that the function m has a weird type in ghci:
> import Data.List
> let m = head . sort
> :t m
m :: [()] -> ()
Why is this the case? Shouldn't it has the type Ord a => [a] -> a? For sort and head I get the expected types:
> :t sort
sort :: Ord a => [a] -> [a]
> :t head
head :: [a] -> a
This is the fault of the dreaded Monomorphism restriction. Basically, because you didn't specify a type for m, GHCi guesses it for you. In this case, it guesses that m should have the type [()] -> (), even though that is clearly not what you want. Just give m a type signature in GHCi and you'll be fine.
> :set +m -- multiline expressions, they're handy
> let m :: Ord a => [a] -> a
| m = head . sort
You can disable the Monomorphism restriction with
> :set -XNoMonomorphismRestriction
But it's usually pretty handy, otherwise you have to specify lots of types for things that you normally wouldn't in interactive mode.
I want to make a toy function that produces a Maybe a and then lift show to make it a Maybe String, but the outcome was weird for me:
λ> :t liftM show . Just
liftM show . Just :: Show a1 => a1 -> Maybe String
λ> liftM show . Just $ 10
Just "10"
λ> let f = liftM show . Just
λ> f 10
<interactive>:9:3:
No instance for (Num ()) arising from the literal `10'
Possible fix: add an instance declaration for (Num ())
In the first argument of `f', namely `10'
In the expression: f 10
In an equation for `it': it = f 10
λ> :t f
f :: () -> Maybe String
λ> let g = liftM show . Just :: (Show a) => a -> Maybe String
λ> :t g
g :: () -> Maybe String
λ> let h = liftM show . Just :: Int -> Maybe String
λ> :t h
h :: Int -> Maybe String
I guess it has something to do with type inference, but I really don't know what happened:
where did that mysterious () come from?
why GHCi didn't complain about ambiguousness?
Dum-duuum!
Next victim of the dreaded monomorphism restriction.
What happens is this: for a definition that looks like a "constant variable" (in the sense that other languages might also use, i.e. not of function type), like f = ..., it is assumed that you wish it to actually behave like a constant (CAF, to be precise). That means, it must not be polymorphic, since with parametric polymorphism there's basically an extra implicit argument to the function (the information which type a1 should be).
To achieve this actual-const-ness, ghci defaults this type variable to whatever specific type it deems least inappropriate. Here, the only constraint is Show; the simplest type fulfilling that is ().
The "correct" way of getting around this is to turn off the monomorphism restriction:
Prelude> :set -XNoMonomorphismRestriction
Prelude> :m +Control.Monad
Prelude Control.Monad> let f = liftM show . Just
Prelude Control.Monad> f 10
Just "10"
Alternatively, you can, like in an actual source file you always should, give proper signatures to identifiers in ghci:
Prelude Control.Monad> let g :: Show a => a -> Maybe String; g = liftM show . Just
Prelude Control.Monad> g 10
Just "10"
Doing that only on the RHS of the = doesn't work, since the monomorphism restriction kicks in only after that is resolved and defaults away the variables (unless, as in h, there are no variables in the first place because you gave a monomorphic signature to the RHS).
Still another thing you can do, simply give the function an explicit argument, then the monomorphism restriction doesn't apply at all. I.e., write it non–point-free:
Prelude Control.Monad> let i a = liftM show $ Just a
Prelude Control.Monad> i 10
Just "10"
So let's say you have a variable n.
You want to check if its an integer, or even better yet check what type it is.
I know there is a function in haskell, isDigit that checks if it is a char.
However is there a function that checks if n is in integer, or even better, gives the type of n?
import Data.Typeable
isInteger :: (Typeable a) => a -> Bool
isInteger n = typeOf n == typeOf 1
But you should think about your code, this is not very much like Haskell should be, and it probably is not what you want.
If you are using an interactive Haskell prompt (like GHCi) you can type :t <expression> and that will give you the type of an expression.
e.g.
Prelude> :t 9
gives
9 :: (Num t) => t
or e.g.
Prelude> :t (+)
gives
(+) :: (Num a) => a -> a -> a
How to I define the equivalent of this function (taken from learnyouahaskell) inside GHCi?
import Data.List
numUniques :: (Eq a) => [a] -> Int
numUniques = length . nub
Without the type declaration, GHCi accepts the function definition, but it ends up with an unhelpful type:
Prelude Data.List> import Data.List
Prelude Data.List> let numUniques' = length . nub
Prelude Data.List> :t numUniques'
numUniques' :: [()] -> Int
The resulting function only accepts a list of units as a parameter.
Is there a way provide type declarations in GHCi? Or is there another way to define functions like these which doesn't require type declarations?
I saw no obvious clues in the GHCi guide, and experimented with expressions like the following (to no avail):
> let numUniques' = ((length . nub) :: (Eq a) => [a] -> Int)
> :t numUniques'
numUniques' :: [()] -> Int
Is there a way provide type declarations in GHCi?
let numUniques' :: (Eq a) => [a] -> Int; numUniques' = length . nub
Or is there another way to define functions like these which doesn't require type declarations?
If you turn off the monomorphism restriction with -XNoMonomorphismRestriction, it will infer the right type.
Note that you can also avoid the monomorphism restriction simply by adding "points" (i.e. explicit variables) back to your expression. So this also gives the correct type:
let numUniques x = length . nub $ x
The GHC User's Guide shows two additional ways to achieve this. This subsection introduces the :{ ... :} construct, which can be used as follows:
> :{
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
| :}
Alternatively, you can enable multiline mode:
> :set +m
> let
| numUniques :: (Eq a) => [a] -> Int
| numUniques = length . nub
|