I realise you could more or less guess how the first argument relates to the next arguments for certain functions was it because you've used those functions before so you remember or because it's actually guessable?
TLDR: you can tell from the function signature, but we're not used to it coming from another language
Example Json.Decode.map2
map2 : (a -> b -> value) -> Decoder a -> Decoder b -> Decoder value
Elm doesn't care what type is a
as long as when you give it all the arguments, all the a
are the same.
so
- if you gave
Json.Decode.string
as 2nd argument - since it returns a
Json.Decode.Decoder String
value, you're saying thata
should beString
- so that first argument
(a -> b -> value)
now has to be(String -> b -> value)
the other way of looking at it: if you KNOW what your first argument is supposed to be e.g. (String -> Int -> User)
then there's no other way: you must give a Decoder String
as 2nd argument and Decoder Int
as 3rd argument.... and you'll magically end up with a Decoder User
as final return value.
I think what I didn't immediately see is that "of course the second and third argument is going to be fed into the first"
That is true (and we could have intuition for that) but not always the case. What's always is only that they have to line up; not what argument feeds into what other argument.
For example, Url.Parser
map : a -> Parser a b -> Parser (b -> c) c
What intuition can I have for this? I provide a first argument of type a
.. and next argument of Parser a b
(i'm losing my ability to understand) and then i'll get a return value of type Parser (b -> c) c
???
Elm doesn't care what type is
a
as long as when you give it all the arguments, all thea
are the same.
You can spell a type variable as anything you want as long as it starts with a lowercased letter. However, there are 3 special type variable names that carry special meaning
-
number
-- if you usenumber
as your type variable, then the type must beInt
orFloat
. In your function body, you get to use mathematical functions on yournumber
variables (look for things that work withnumber
)myfunc : number -> number -> number myfunc a b = a * b
-
comparable
-- if you usecomparable
as your type variable, then the type must beInt
,Float
,Char
,String
,List comparable
, orTuple comparable comparable
. In your function body, you also get to use comparison functions on yourcomparable
variablesmyfunc : comparable -> comparable -> Bool myfunc a b = a > b
-
appendable
-- if you useappendable
as your type variable, then the type must beString
orList a
. In your function body, you also get to use the++
functionmyfunc : appendable -> appendable -> appendable myfunc a b = a ++ b
If your type signature needs multiple different number
types (or different comparable
or appendable
), just suffix the special type variable names with numbers, e.g.
myfunc : number -> number1 -> number2 -> comparable -> comparable1