{- Solutions to CS 291 Assignment #1 -} -- jumpy squares its second argument then mods by the first. -- I've used ` quotes to convert the built-in mod function -- to infix form. jumpy cutoff n = (n * n) `mod` cutoff -- We get boundedJumpy by applying jumpy to 25. No need for -- additional arguments. Since (jumpy 25) produces a function -- expecting one additional arg, boundedJumpy does as well. boundedJumpy = jumpy 25 -- Recursively visit each of the values between low and high. -- If we're at the base case, just return whatever boundedJumpy -- does. Otherwise, call boundedJumpy once, make a recursive call -- to do the rest, and see which result "wins". maxFinder low high | low == high = boundedJumpy high | high < low = error "First argument must be <= the second" | otherwise = max (boundedJumpy low) (maxFinder (low+1) high) -- average moves n and m closer to each other until they meet. -- This could either be because they collide at the same value -- (the first case), or they're adjacent values (the second -- case). The recursive case increments the lower bound and -- decrements the upper so they get closer together. -- The "adjacent" base case adds 1/2, a Fractional value, to -- n. The type constraints on the + operator require that both -- operands have the same type, which would require that n also -- be Fractional. The fromIntegral function takes an Integral -- type and "liberates" it back to being a Num, which keeps + -- happy while still allowing n to be of type Integral. average n m | n == m = fromIntegral(n) | n+1 == m = fromIntegral(n)+1/2 | m < n = error "First argument must be <= the second" | otherwise = average (n+1) (m-1) -- A copy-n-paste job, except that the parameters are now in -- tuple form. avgTuple (n, m) | n == m = fromIntegral(n) | n+1 == m = fromIntegral(n)+1/2 | m < n = error "First argument must be <= the second" | otherwise = avgTuple (n+1, m-1) -- NOTE: recursive call takes tuple now! -- A nicer way to write the tuple-based version is this: avgTuple2 (n, m) = average n m -- Here's one way to write a function with the desired type signature. -- It takes two tuples as inputs, and returns one of them based on the -- Boolean argument. foo (n,m) (_,_) True = (n,m) foo (_,_) (n,m) False = (n,m) -- An inferior approach to this one is to write a function that's -- uselessly vague, then restrict its type to the desired type via a -- type declaration. For example: bar :: (a,b) -> (a,b) -> Bool -> (a,b) bar a b c = a