Reputation: 281
xs = [1,2,3]::[Float]
ys = map (+) xs
This was a question in an old test and there is no solution sheet.
The questions:
1) What kind of signature does ys
have?
2) Explain why and draw how ys
looks like
For the first question I know that xs
is of type float
and so should ys
(I run the program in ghci too).
As for the second one I have no idea, because when I run the code nothing happens. When I run it and the run ys
on a separate row I get an error.
Can someone help me with a hint?
Upvotes: 0
Views: 75
Reputation: 120751
For the first question I know that
xs
is of typefloat
er, no. xs
has type [Float]
: a list of floats.
and so should
ys
ys
does not have the same type as xs
. You probably think so because you've read that +
requires the arguments and result to have the same type:
(+) :: Num a => a -> a -> a
...or if you instantiate it to Float
numbers
(+) :: Float -> Float -> Float
This is correct, nevertheless (+)
is not an endomorphism (a function mapping a type to itself, as it would have to be if ys
was the same type as xs
) because it has two number arguments.
With map (+)
you're considering (+)
as a function of a single argument, not of two arguments. In most programming languages this would actually be an error, but not so in Haskell: in Haskell, all functions actually have only one argument. Functions with “multiple arguments” are really just functions on interesting types, that make it seem as if you're passing multiple arguments. In particular, the signature of (+)
is actually shorthand for:
(+) :: Float -> (Float -> Float)
So, considered as a one-argument function, (+)
actually maps numbers to number-endomorphisms. Hence,
map (+) :: [Float] -> [Float -> Float]
and
ys :: [Float -> Float]
– a list of number-functions. Specifically, it's this list:
ys = [(+) 1 , (+) 2 , (+) 3 ]
≡ [(1+) , (2+) , (3+) ]
≡ [\n -> 1+n, \n -> 2+n, \n -> 3+n]
I could, for example, use it like this:
GHCi> let [f,g,h] = ys in [f 3, g 2, h 1]
[4,4,4]
GHCi> map ($ 10) ys -- applies all functions separately to the number 10
[11,12,13]
GHCi> foldr ($) 0 ys -- applies all the functions one after another to 0
6
BTW, IMO you're asking the question the wrong way around. In Haskell, you don't want to consider some code and wonder what type it has – that is more an ML or even Lisp approach. I'd always start with the type signature, and work out the implementation “outside to in” (typed holes are very handy for this). This possibility is one of the big advantages of functional programming in comparison to procedural languages.
Upvotes: 3
Reputation: 598
ys type is [Float -> Float]
, a list of functions that receive a number return the number +1 (first elem), the number + 2 (the second) and the number +3 (the last).
Please, bear in mind that +
is a is applied with a single argument for each list element so it does return another function.
If you wanted to add all the items in the List, you should use a reduce function, such as foldl
.
let zs = foldl (+) 0 xs
I hope this helps.
Cristóbal
Upvotes: 1
Reputation: 2897
I don't have ghci at the moment, apologies if something I say is wrong.
xs
is type [Float]
and ys
is of type [Float -> Float]
(it's a list of functions that each take a Float
and return a Float
). ys
will be [(+) 1, (+) 2, (+) 3]
because map
applies (+)
to each elements in xs
. But you cannot print ys
because functions do not derive Show
Upvotes: 2