{- Notes on Haskell. Type :q to leave hugs -} 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 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? {- code for assignment 3 starts here --} -- insert this file into haskell.hs in an appropriate place -- then save and run the resulting file -- hw 3 -- exercise 1 -- make sure it returns a list, empty or one element lastOne [] = [] lastOne (x:xs) = if (null(xs)) then [x] else lastOne xs -- exercise 2 revStr [] = [] revStr (x:xs) = revStr(xs)++[x] -- exercise 3 -- is it a palindrome? isPal [] = True isPal (x:xs) = if (null(xs)) then True else if (x /= head(lastOne(xs))) then False else isPal(allButLast(xs)) -- exercise 4 isUp x = if ('A' <= x) && (x <= 'Z') then 1 else 0 countUppers [] = 0 countUppers (x:xs) = isUp(x) + countUppers(xs) countUppers2 x = foldr (+) 0 (map isUp x) -- exercise 5 is omitted -- exercise 6 sumSeries n = foldr (+) 0 (map (\x -> x^2) [1..n]) -- exercise 7 selectN n aList | n > length(aList) = [] | n == 1 = [head(aList)] | otherwise = selectN (n-1) (tail(aList)) -- exercise 8 -- two solutions -- exercise 8 gsplitlist::[a] -> ([a],[a]) gsplitlist [] = ([],[]) gsplitlist (x:xs) = if length(xs) == 0 then ([x],[]) else (half1,half2) where tmp = gsplitlist(allButLast(xs)) half1 = x:fst(tmp) half2 = snd(tmp)++lastOne(xs) splitlist::[a] -> ([a],[a]) splitlist aList = (part1, part2) where n = length(aList) n2 = n `div` 2 n1 = n - n2 inPart1 = map (\i -> i <= n1) [1..n] inPart2 = map (\i -> i > n1) [1..n] sieve1 = zip inPart1 aList sieve2 = zip inPart2 aList half1 = filter (\x -> fst(x)) sieve1 part1 = map (snd) half1 half2 = filter (\x -> fst(x)) sieve2 part2 = map (snd) half2 demohw3 = do let aList = [1,2,4,6,9] -- putStrLn("aList is "++show(aList)) putStrLn("lastOne "++show(aList)++" is "++show(lastOne(aList))) putStrLn("reverse of foobar is "++revStr("foobar")) putStrLn("is foobar a palindrome? "++show(isPal("foobar"))) putStrLn("is rabbar a palindrome? "++show(isPal("rabbar"))) putStrLn("number of uppers in foobar is "++show(countUppers("foobar"))) putStrLn("number of uppers in fOObar is "++show(countUppers("fOObar"))) putStrLn("number of uppers in fOoBaR is "++show(countUppers2("fOoBaR"))) putStrLn("sum of square from 1 to 3 should be 14: "++show(sumSeries(3))) putStrLn("selectN 7 aList is "++show(selectN 7 aList)) putStrLn("selectN 1 aList is "++show(selectN 1 aList)) putStrLn("selectN 5 aList is "++show(selectN 5 aList)) let (part1,part2) = splitlist [1] putStrLn("part1 of splitlist [1] is "++show(part1)) putStrLn("part2 of splitlist [1] is "++show(part2)) let (part1,part2) = splitlist([3,4]) putStrLn("part1 of splitlist [3,4] is "++show(part1)) putStrLn("part2 of splitlist [3,4] is "++show(part2)) let (part1,part2) = splitlist(aList) putStrLn("part1 of splitlist aList is "++show(part1)) putStrLn("part2 of splitlist aList is "++show(part2)) {- code for assignment 3 ends here -} 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))