Control.Parallel
:
-- Spark a parallel computation
par :: a -> b -> b
-- f x = heavy1 x + heavy2 x
f x = par y1 (par y2 (y1 + y2))
where
y1 = heavy1 x
y2 = heavy2 x
par
does not change the result.
par
,
it is still correct with par
!
map
pmap :: (a -> b) -> [a] -> [b] pmap f [] = [] pmap f (x:xs) = par y (par ys (y:ys)) where y=f x ys=pmap f xs
Only a small change in one place. Results:
Threads | Solver A | Solver B |
---|---|---|
1 | 14.0s | 7.9s |
2 | 7.3s | 5.3s |
4 | 4.2s | 2.9s |
8 | 4.0s | 2.5s |
choose b x y = if b then x else y
choose
:help
Commands available from the prompt:
...
:print [<name> ...] show a value without forcing its computation
:sprint [<name> ...] simplified version of :print
...
ones = 1 : ones numbers = [1..] -- count n = [n..] countUp n = n:countUp (n+1) -- fromTo start stop == [start .. stop] fromTo start stop = take (stop-start+1) (countUp start) -- Fibonacci numbers fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
primes :: [Integer] primes = sieve [2..] where sieve (p:xs) = p:sieve [x|x<-xs,x `mod` p /= 0]
-- | The twenty first primes ex1 = take 20 primes -- | All primes below 100 ex2 = takeWhile (<100) primes
repeat :: a -> [a]
cycle :: [a] -> [a]
iterate :: (a->a) -> a -> [a]
enumFrom :: Enum a => a -> [a] -- depending on the type
repeat 1 == [1,1,1,1,…]
cycle [1,2,3] == [1,2,3,1,2,3,1,2,3,1,2,3,…]
iterate (*2) 1 == [1,2,4,8,16,32,64,128,256,512,…]
[0..] == enumFrom 0 == [0,1,2,3,4,5,6,7,8,9,…]
repeat
generates an infinite list but we can use it
even if we only want a finite list.
replicate :: Int -> a -> [a] replicate n x = take n (repeat x)
filter
returns all elements of a list that pass
a test, but we can use it even if we only want the first one.
find :: (a->Bool) -> [a] -> Maybe a find p xs = listToMaybe (filter p xs)
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices p xs = [ i | (i,x) <- zip [0..] xs, p x]
sqroot x = head [a2 | (a1,a2) <- zip as (tail as), abs (a1-a2)<1e-10] where as = iterate next 1 -- infinite list of improving approx. next a = (a+x/a)/2 -- the next approx.
zip
zip (x:xs) (y:ys) = (x,y):zip xs ys zip _ _ = []
xs
ys
prop_zip_length xs ys = length (zip xs ys) == min (length xs) (length ys)
zip [1..] "Haskell"
[(1,'H'),(2,'a'),(3,'s'),(4,'k'),(5,'e'),(6,'l'),(7,'l')]
length [1..]
length
length
(+)
Int
length [] = 0 length (x:xs) = 1 + length xs
data Nat = Z | S Nat deriving (Eq,Ord,Show)
infinity = S infinity
length :: [a] -> Nat length [] = Z length (x:xs) = S (length xs)
length primes > 1000
primes
prop_zip_length [1..] "Haskell"
True
arbitrary :: Gen [a]
prop_reverse_reverse xs = reverse (reverse xs) == xs
search :: (Nat->Bool) -> Maybe Nat
search p
Just n
n
p n == True
Nothing
p n == False
n
search (\ n -> n*n==25)
Just (S (S (S (S (S Z)))))
search (\ n -> n*n==26)
Nothing
data Tree a = Leaf a | Branch (Tree a) (Tree a) eqTree :: Eq a => Tree a -> Tree a -> Bool eqTree (Leaf a1) (Leaf a2) = a1==a2 eqTree (Branch l1 r1) (Branch l2 r2) = eqTree l1 l2 && eqTree r1 r2 eqTree _ _ = False
False
(&&)
eqFringe :: Eq a => Tree a -> Tree a -> Bool
False
readFile
countLines :: FilePath -> IO Int countLines filename = do s <- readFile filename return (length (lines s))
sortFile :: FilePath -> IO () sortFile filename = do input <- readFile filename writeFile filename (sortLines input) where sortLines = unlines . sort . lines
sortFile