{- Notes on Haskell. compile with the command "ghc haskellHandout.hs" print this handout with 'enscript -2r -M Letter haskellHandout.hs' -} import qualified Data.Char as Char import System.Random increment :: Int -> Int -- functions have signatures increment x = x+1 -- and definitions and1 :: Bool -> Bool -> Bool and1 x y = if x==True && y==True then True else False and2 :: Bool -> Bool -> Bool -- two Bool input args and2 True True = True -- and pattern matching and2 _ _ = False -- with underscore as a wildcard fact :: Integer -> Integer fact 0 = 1 fact n = n*fact(n-1) --roots :: Float -> Float -> Float -> (Float, Float) roots a b c = if discrim<0 then (0,0) else (x1, x2) where discrim = b*b - 4*a*c e = -b/(2*a) x1 = e + sqrt discrim / (2*a) x2 = e - sqrt discrim / (2*a) --- some list functions listLen1 :: [a] -> Int listLen1 [] = 0 listLen1 (x:xs) = 1 + listLen1(xs) -- here's another (faster) way to do listLen listLen2 :: [a] -> Int listLen2 = sum . map (const 1) demo1 = do putStrLn "demo1" putStrLn ("demo of increment - should be 4: " ++ show(increment(3))) putStrLn ("demo of logical constants, should be True: " ++ show(0==0)) putStrLn ("demo of logical constants, should be False: " ++ show(0==1)) putStrLn ("demo of and1 - should be True: " ++ show(and1 True True)) putStrLn ("demo of and1 - should be False: " ++ show(and1 False True)) putStrLn ("demo of and2 - should be True: " ++ show(and2 True True)) putStrLn ("demo of and2 - should be False: " ++ show(and2 False True)) putStrLn ("demo of fac - should be 720: " ++ show(fact(6))) putStrLn "demo of roots" putStrLn (show(roots 2.0 1.0 1.0)) -- NaN putStrLn (show(roots 2.0 6.0 1.0)) -- normal output -- ord ch is the ASCII code for any character ch -- Haskell strings are lists of characters, so all the list functions work -- including map code x = map Char.ord x -- string -> [Int] uncode ch = map Char.chr ch -- [Int] -> string demoAscii = do let aString = "foobar" putStrLn ("demo of code: " ++ show(code(aString))) putStrLn ("demo of uncode: " ++ show(uncode(code(aString)))) isVowel 'a' = True isVowel 'e' = True isVowel 'i' = True isVowel 'o' = True isVowel 'u' = True isVowel x = False -- using if/then/else anyVowels [] = False anyVowels (c:cs) = if isVowel(c) then True else anyVowels(cs) -- using guards anyVowels2 [] = False anyVowels2 (c:cs) | isVowel(c) = True | otherwise = anyVowels2(cs) -- using map anyVowels3 [] = False anyVowels3 aString = or (map isVowel aString) -- using filter anyVowels4 [] = False anyVowels4 aString = if vlen > 0 then True else False where vlen = length (filter isVowel aString) sumList :: [Int] -> Int sumList [] = 0 sumList (x:xs) = x + sumList(xs) sumList2 :: [Int] -> Int sumList2 aList = foldr (+) 0 aList zipDemo = print(zip [1,3..9] [0,2..8]) demo2 = do let aList = [1,2,4,7,9] putStrLn ("length of aList, according to listLen1, is " ++ show(listLen1 aList)) putStrLn ("length of aList, according to listLen2, is " ++ show(listLen2 aList)) putStrLn ("sum of aList, according to sumList, is " ++ show(sumList aList)) putStrLn ("sum of aList, according to sumList2, is " ++ show(sumList2 aList)) let string1 = "great big cats" -- let string1 = "grt bg cts" putStrLn ("anyVowels( "++string1++" ) is "++show(anyVowels string1)) putStrLn ("anyVowels2( "++string1++" ) is "++show(anyVowels2 string1)) putStrLn ("anyVowels3( "++string1++" ) is "++show(anyVowels3 string1)) putStrLn ("anyVowels4( "++string1++" ) is "++show(anyVowels4 string1)) zipDemo radius :: [(Float,Float)] -> [Bool] radius [] = [] radius (x:xs) = radius2(x):radius(xs) radius2 :: (Float,Float) -> Bool radius2 (x,y) = if x^2+y^2<1.0 then True else False aRandom :: Int -> [Float] aRandom seed = randomRs (0.0, 1.0) . mkStdGen $ seed nRandoms :: Int -> Int -> [Float] nRandoms n seed = take n . randomRs (0.0, 1.0) . mkStdGen $ seed --calcpi :: Int -> Int -> Double calcpi k1 k2 = fromRational(4*toRational(k2)/toRational(k1)) makePairs [] =[] makePairs (x:xs) = (x,y):makePairs(ys) where y = head(xs) ys = tail(xs) getk2 k1 = listLen2(inCircle) where someXs = nRandoms k1 271828 someYs = nRandoms k1 828459 pairs = zip someXs someYs radii = map (radius2) pairs inCircle = filter ((==) True) radii calcpi2 k1 = fromRational(4*toRational(k2)/toRational(k1)) where someRandoms = nRandoms (k1*2) 271828 k2 = length(filter ((==) True) (map (radius2) (makePairs(someRandoms)))) -- you may use this for exercise 3 allButLast [] = [] allButLast (x:xs) = if null(xs) then [] else x:allButLast(xs) -- hints for exercise 8 -- recursive approach -- need to explain fst and snd -- some code like this may be used: -- where tmp = gsplitlist(allButLast(xs)) -- half1 = x:fst(tmp) -- half2 = snd(tmp)++lastOne(xs) -- high-order function approach -- n = length(aList) -- n2 = n `div` 2 note the integer division -- note the lambda expression, aka anonymous function -- inPart1 = map (\i -> i <= n1) [1..n] what's the type of this new list? -- sieve1 = zip inPart1 aList what's the type of this new list? -- half1 = filter (\x -> fst(x)) sieve1 what's the length of this new list? -- part1 = map (snd) half1 what's the type of this new list? main = do demo1 demo2 demoAscii -- demohw3 let k1 = 100 putStrLn("k1 is " ++show(k1)) let approxpi = calcpi2 k1 putStrLn("approximate value of pi " ++show(approxpi))