It's nonsensical to write things like drop :: [1,2,3,4] -> (2 -> [3,4])
or 2 -> ([1,2,3,4] -> [3,4])
– you're mixing type-level and value-level notations there. What you should instead do is look at local types of subexpressions:
drop 2 [1,2,3,4]
└─┬┘ ┊ └──┬────┘
┌─┴───────────────┐ ┌─┴─┐ ┌──┴──┐
│Int->[Int]->[Int]│ │Int│ │[Int]│
└─────────────────┘ └───┘ └─────┘
Add the implied parentheses
(drop 2) [1,2,3,4]
└┬─┘ ┊ └──┬────┘
┌─┴─────────────────┐ ┌─┴─┐ ┌──┴──┐
│Int->([Int]->[Int])│ │Int│ │[Int]│
└───────────────────┘ └───┘ └─────┘
Now the subexpression drop 2
means you're applying the argument 2
as the first argument of the function drop
, i.e. as the Int
in its signature. For the whole drop 2
expression, this argument has therefore vanished:
( drop 2 ) [1,2,3,4]
┊ ┌──────────┴────────┐ ┌─┴─┐ ┊ └──┬────┘
┊ │Int->([Int]->[Int])│ │Int│ ┊ ┊
┊ └───────────────────┘ └───┘ ┊ ┊
└────────────┬─────────────────┘ ┌──┴──┐
┌────┴───────┐ │[Int]│
│[Int]->[Int]│ └─────┘
└────────────┘
This is analogous to applying the single-argument function length :: [Bool] -> Int
to the single argument [False,True] :: [Bool]
to get the result length [False,True] ≡ (2::Int)
. The fact that for drop
the result has type ([Int]->[Int])
instead of something “atomic” like Int
is irrelevant at this stage.
Then on the outer level, you're applying the function of type [Int]->[Int]
to the argument of type [Int]
, which is perfectly sensible. The whole thing then has simply result type [Int]
.
( ( drop 2 ) [1,2,3,4] )
┊ ┊ ┌──────────┴────────┐ ┌─┴─┐ ┊ └──┬────┘ ┊
┊ ┊ │Int->([Int]->[Int])│ │Int│ ┊ ┊ ┊
┊ ┊ └───────────────────┘ └───┘ ┊ ┊ ┊
┊ └────────────┬─────────────────┘ ┊ ┊
┊ ┌────┴───────┐ ┌──┴──┐ ┊
┊ │[Int]->[Int]│ │[Int]│ ┊
┊ └────────────┘ └─────┘ ┊
└────────────────────────┬────────────────────┘
┌──┴──┐
│[Int]│
└─────┘
(drop 2) ([1,2,3 4] -> [3,4])
right? – Buoyancydrop 2
is. It thus evaluates(drop 2)
which has type[a] -> [a]
, and that function is then applied to[1,2,3,4]
. – AcrodromeputStrLn "foo" >> (putStrLn "bar" >> putStrLn "baz")
prints "foo" first even thoughputStrLn "bar"
is in brackets. – Unboned