I am using the "Learn you a haskell tutorial" and have reached the type declarations section. I understand that they change the way GHCI gives you an error message, but do they also affect the way the actual function works? If not, is it essentially like a python function documentation written with """ """ underneath "def someFunction(x): "? - just an example
Example code:
removeNonUppercase :: [Char] -> [Char]
removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]
EDIT: I ask this because the tutorial explains that haskell is type-inferred at compile time.
Signatures aren't just for documentation (even though they are very useful for that as well). They are enforced by the compiler, which means that by adding signatures you can make the types of your functions more restrictive than they would be otherwise. Toy example:
add x y = x + y
addInt :: Int -> Int -> Int
addInt x y = x + y
*Main> :t add
add :: Num a => a -> a -> a
*Main> add 2 3
5
*Main> add 2.1 3.1
5.2
*Main> :t addInt
addInt :: Int -> Int -> Int
*Main> addInt 2 3
5
*Main> addInt 2.1 3.1 -- addInt will not accept non-Ints.
<interactive>:23:8:
No instance for (Fractional Int) arising from the literal ‘2.1’
In the first argument of ‘addInt’, namely ‘2.1’
In the expression: addInt 2.1 3.1
In an equation for ‘it’: it = addInt 2.1 3.1
Besides that, adding type signatures means you will get better (i.e. easier to understand) errors in tricky situations, as the compiler will know what you want to achieve rather than having to guess everything on its own.
There are also situations in which the compiler can't decide the types without the help of some signatures or other type annotations. Perhaps the simplest example is:
readAndShow s = show (read s)
If you try to use that without specifying any types...
Foo.hs:6:17:
No instance for (Show a0) arising from a use of ‘show’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance (GHC.Arr.Ix a, Show a, Show b) => Show (GHC.Arr.Array a b)
-- Defined in ‘GHC.Arr’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
...plus 26 others
In the expression: show (read s)
In an equation for ‘readAndShow’: readAndShow s = show (read s)
Foo.hs:6:23:
No instance for (Read a0) arising from a use of ‘read’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance (GHC.Arr.Ix a, Read a, Read b) => Read (GHC.Arr.Array a b)
-- Defined in ‘GHC.Read’
instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’
instance (Integral a, Read a) => Read (GHC.Real.Ratio a)
-- Defined in ‘GHC.Read’
...plus 25 others
In the first argument of ‘show’, namely ‘(read s)’
In the expression: show (read s)
In an equation for ‘readAndShow’: readAndShow s = show (read s)
Failed, modules loaded: none.
... it won't work. read
converts a String
to some type, and show
does the opposite. However, if nothing specifies the type of read s
, the compiler can't tell which type you want to read the String
as. So you either need to specify the intermediate type...
readAndShowAsInt s = show (read s :: Int)
*Main> readAndShowAsInt "2"
"2"
... Or have something else pick the type for you:
readAndAdd :: String -> Int -> Int
readAndAdd s y = read s + y
*Main> readAndAdd "2" 3
5
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With