\begin{code}
{-# OPTIONS_GHC -Wall #-}
module Jan21 where
import Prelude hiding (curry, uncurry)
\end{code}
Learning objectives:
\begin{itemize}
\item higher-order functions
\end{itemize}
recall: ($) is ‘apply’, with very low precedence.
Main use: fewer parenthesizes!
\begin{code}
weirdo :: [a -> c] -> [a] -> [c]
weirdo = zipWith ($)
\end{code}
Explaining the type:
\begin{verbatim}
Prelude> :t ($)
($) :: (e -> d) -> e -> d
Prelude> :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
\end{verbatim}
So that means that, when you put ($) for the first arg, you get:
a = e -> d
b = e
c = d
so
weirdo = zipWith ($) :: [c -> d] -> [c] -> [d]
\begin{code}
mapFun :: [a -> b] -> a -> [b]
— v3
mapFun f x = map ($ x) f
— v2
— mapFun f x = map (\g -> g $ x) f
— v1
— mapFun [] _ = []
— mapFun (f : fs) x = f x : mapFun fs x
\end{code}
More fun with “higher order functions”
\begin{code}
curry :: ((a, b) -> c) -> (a -> b -> c)
— equivalent to curry :: ((a, b) -> c) -> a -> b -> c
— equivalent to curry :: ((a, b) -> c) -> (a -> (b -> c))
— NOT equivalent to curry :: ((a, b) -> c) -> (a -> b) -> c
curry f = \a b -> f (a, b)
— also
— curry f a b = f (a, b)
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f (x, y) = f x y
— uncurry g = \(x, y) -> g x y
\end{code}
Side item: Haskell B. Curry was a logician…
As you might guess, these are inverses…
However:
– hard to prove: uncurry . curry = id
– still hard: forall f. (uncurry . curry) f = f
– bingo! : forall f :: ((a,b) -> c), x::a, y::b
(uncurry . curry) f (a , b) = f (a , b)
Proof:
assume f :: ((a,b) -> c), x::a, y::b
(uncurry . curry) f (x , y) = — expand definition of (.)
(uncurry (curry f)) (x , y) = — expand curry
(uncurry (\a b -> f (a, b)) (x , y) = — expand uncurry
(\(w, z) -> (\a b -> f (a, b)) w z) (x , y) = — expand outer application
(\a b -> f (a, b)) x y = — expand application
f (x, y)
Other direction is “the same”, i.e curry . uncurry = id
What did I do to go from “hard” to possible? I *saturated*, applied fully.
(eta expanding)