[Haskell-cafe] [] vs [()]
Jonathan Cast
jonathanccast at fastmail.fm
Fri Oct 10 14:30:09 EDT 2008
On Fri, 2008-10-10 at 11:14 -0700, Daryoush Mehrtash wrote:
>
> I don't think any clarity is added by made-up notation. I
> think you
> mean
> In fact I was "trying" to be correct on this.
Great!
> Is it wrong to show:
>
> [()] >> f = f
>
> as was doing:
>
> [()] map f = [f]
Yes. Juxtaposition is always application in Haskell, and is always
left-associative, and binds more tightly than any other operator. So
your left-hand side means [()] applied to two arguments, map and f.
This is not legal Haskell, because [()] is not a function. You intended
to apply the function map to two arguments, f and [()]. The notation
for that is
map f [()]
so, making that change, you get
map f [()] = [f]
This is still wrong:
map :: (a -> b) -> [a] -> [b]
so if
f :: (() -> b)
then
map f [()] :: [b]
but if
f :: (() -> b)
then
[f] :: [() -> b]
Unification of these types (required for an equation between the two
terms) proceeds as follows:
[b] = [() -> b]
so b = () -> b
But the unifier doesn't have a rule to solve recursive equations on
types like the above; so unification fails; your rule isn't even
well-typed.
The correct rule is
map f [()] = [f ()]
where
f () :: b
so
[f ()] :: [b]
so everything type-checks.
(>>) is different from map in three ways:
(1) The arguments are in a different order. It's a minor issue, but of
course you have to get it right.
(2) >> is an infix operator (syntactically distinct from functions: map
and (>>) are functions while `map` and >> are infix operators). So you
can use it in the middle of your left-hand side.
(2) (>>) has some subtle differences from map. The definitions are,
roughly:
map f xn = xn >>= \ x -> return (f x)
xn >> ys = xn >>= \ x -> ys
map does something interesting with the elements of its argument list:
it passes them to the function f (it also builds a list of the result,
which (>>) leaves to its second argument). (>>) just ignores those
elements. This difference is reflected by the types, as well:
map :: (a -> b) -> [a] -> [b]
The type variable `a' appears twice, so in (map f xn) you know the
argument to f and the elements of xn are related (in some way).
(>>) :: [a] -> [b] -> [b]
The type variable `a' appears only once, so in (xn >> ys) the elements
of xn are just ignored; only the list structure matters.
>
> I want to say map function f over a single element list will yield a
> list of single element, the element being function f.
Haskell does distinguish between a function and the result of applying
that function to an argument, so the element *isn't* actually f --- it's
the result of applying f to an argument.
jcc
More information about the Haskell-Cafe
mailing list