TallCat

Logo

Webpage of the Compositional Systems and Methods group at TalTech.

Functional Programming Exercise Session 4

  1. Write a function running_sum : IO Nat that descricbes a computation in which the user is repeatedly prompted to enter a number (a Nat) until they enter a string that does not represent a number, at which point the sum of all numbers entered is returned. For example:
    > :exec running_sum 
    > enter a number:
    > 5               (user input)
    > enter a number:
    > 42              (user input)
    > enter a number:
    > 16              (user input)
    > enter a number:
    > I'd rather not  (user input)
    > 63              (final return value)
    

    If the user enters no numbers, the computation should return 0.

  2. Write a function in_sequence : List (IO ()) -> IO () which, given a list of descriptions of computations that don’t return anything, describes the computation in which each of the input computations is carried out in sequence. For example:
    > :exec (in_sequence [ putStrLn "hello", putStrLn "world"])
    > hello
    > world
    
  3. Write a function collect_results : List (IO a) -> IO (List a) which, given a list of descriptions of computations that return something of type a, describes the computation in which each of the input computations is carried out in sequence, and returns the list of results obtained. For example:
    > :exec (collect_results [ getLine, pure "there", getLine ])
    > hello                           (user input)
    > computer                        (user input)
    > ["hello", "there", "computer"]  (final return value) 
    
  4. Write a function once_definitely : String -> String -> (String -> Maybe a) -> IO a such that, for example:
    > :exec (once_definitely "enter a Nat: " "That's not a Nat! Try again!" parsePositive)
    > Enter a Nat:
    > I don't want to!    (user input)
    > That's not a Nat! Try again!
    > Enter a Nat:
    > You can't make me!  (user input)
    > That's not a Nat! Try again!
    > Enter a Nat:
    > Please, let me go.  (user input)
    > That's not a Nat! Try again!
    > Enter a Nat: 
    > 5                   (user input)
    > 5                   (final return value)
    

    The idea being that in once_definitely prompt err_msg foo, prompt is the prompt we display to the user, foo : String -> Maybe a tries to parse the user’s string to obtain an a. If parsing succeeds, we return the value thus obtained. If parsing fails, we display our error message err_msg, and try again.

  5. Say that a Nat is palindromic in case reversing its base 10 digits yields the same Nat. For example 8, 0, and 131 are palindromic, but 52, 10, and 466 are not. Write a function ensure_palindrome : Nat -> Maybe Nat such that ensure_palindrome n is Nothing if the n is not palindromic, and is Just n if n is palindromic. Note that reversing the digits of 10 yields 01 = 1, and so on for any number of trailing zeroes.

  6. This question has three parts.

    A: Write two more functions ensure_odd : Nat -> Maybe Nat and ensure_prime : Nat -> Maybe Nat which ensure that the input is odd and prime respectively (this should be easy now!).

    B: Suppose have a list of properties we would like to ensure that a Nat satisfies, given as functions Nat -> Maybe Nat as above. Write a function that collects the list of properties into a single property Nat -> Maybe Nat that holds in case all the properties in our list of properties hold. That is, write a function unify_properties : List (Nat -> Maybe Nat) -> (Nat -> Maybe Nat).

    C: Use unify_properties to compute the sum the first 10 Nats that are odd, prime, and palindromic.