foldl
, foldr
, foldl'
foldr
foldr op init [] = init
foldr op init (x:xs) = x `op` (foldr op init xs)
foldl
foldl op init [] = init
foldl op init (x:xs) = foldl op (init `op` x) xs
foldr
lends itself to laziness. foldr (&&) False (repeat False)
foldl
does not lend it to laziness, but it can be more efficient in some cases, with some cleverness.
foldr (+) 0 [1..1000000]
.foldr (+) 0 [1..1000000]
= 1 + (foldr (+) 0 [2..1000000])
= 1 + (2 + (foldr (+) 0 [3..1000000]))
.
.
.
= 1 + (2 + ... + (1000000 + 0)))
= 1 + (2 + ... (+ 1000000))
=
.
.
.
.
= ...
foldl (+) 0 [1..1000000]
foldl (+) 0 [1..1000000]
= foldl (+) (0+1) [2..1000000]
= foldl (+) ((0+1)+2) [3..1000000]
.
.
.
= ((0 + 1) + 2) ... 1000000)
.
.
.
= ....
foldl'
foldl' op init [] = init
foldl' op init (x:xs) = let z = (init `op` x) in seq z (foldl' op z xs)
import Debug.Trace
myfun a b | trace ("myfun " ++ show a ++ " " ++ show b) False = undefined
myfun a b = ...
cylinder r h
| trace ("calling cylinder with r = " ++ show r ++ " and h = " ++ show h) False =
undefined
cylinder r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^2
in sideArea + 2 * topArea
import
import ... hiding ...
import qualified ...
import qualified ... as ...
module ... (...) where
type IncreasingList = [Int]
type Trace a = Int -> a
newtype Feet = Feet Double
newtype Cm = Cm Double
data Ellipse = MkEllipse Float Float
ellipseArea :: Ellipse -> Float
ellipseArea (MkEllipse major minor) = pi * major * minor
data Ellipse = Ellipse Float Float
data Ellipse = Ellipse {major :: Float, minor :: Float}
Interlude: deriving Show
Updating Record Syntax
ellipseA = Ellipse 1.0 9.0
ellipseB = ellipseA {major = 10.0}
data Day = Saturday | Sunday | Monday | Tuesday | Wednesday | Thursday | Friday
data Shape = Rectangle Float Float | Square Float
area :: Shape -> Float
area (Rectangle a b) = a * b
area (Square a) = a * a
:t Singleton
makes sense but :t NonEmpty
does notdata List a = Nil | Cons a (List a)
data NonEmpty a = Singleton a | More a (NonEmpty a)
data Stream a = Stream { head :: a, tail :: (Stream a) }
data Mealy a b = Mealy { mOut :: a -> b, mNext :: a -> Mealy a b }
ones :: Stream Int
ones = Stream 1 ones
mealySimple :: Mealy Int String
mealySimple = Mealy { mOut = show, mNext = \x -> mealySimple }
Either
(->)
are anonymous exponentialsMaybe
lookup :: Int -> [(Int, b)] -> b
lookup i tab = snd . head $ filter (\(x,y) -> x == i) tab
lookup _ [] = Nothing
lookup i (k, v):xs
| i == k = Just v
| otherwise = lookup i xs
:k Int
:k (Maybe Int)
:k Maybe
:k Either
data Fix f = Fix { unFix :: f (Fix f) }
.
Fix
has kind (* -> *) -> *
deriving Show
do?
Show
is a typeclass. Similar to interfaces in Java:i Show
data Ellipse = Ellipse {major :: Float, minor :: Float}
instance Show Ellipse where
show (Ellipse major minor)
| major == minor = "Just a circle"
| otherwise = "Another ellipse"
lookup
?
Int
to a
myLookup :: Int -> [(Int, b)] -> Maybe b
myLookup _ [] = Nothing
myLookup i (k, v):xs
| i == k = Just v
| otherwise = lookup i xs
Paramteric vs Ad-Hoc Polymorphism
generalizing quicksort
Ord
typeclassquicksort (x : xs) = lesser ++ [x] ++ greater
where
lesser = [y | y <- xs, y <= x]
greater = [y | y <- xs, y >= x]
Eq a => Ord a
. For a
to be Ord
, it must first be Eq
Ord a => Ord [a]
data Two = One | Two deriving (Ord, Show)
testCompare = [One, Two] < [One, One]
:k Ord