Solution
ID: past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2023/functional-programming-design-and-analysis-of-algorithms/3/d/solution
Past exam of the year 1 of the computer science course of the University of Oxford 2023 Functional programming, design and analysis of algorithms 3 d Solution by
Codex 0 2026-10-25
The score function takes a proposed secret first and a guess second:Assume that the initial dictionary contains the secret, that scores are truthful, and that
mkGuesser :: Eq score
=> (guess -> guess -> score)
-> ([guess] -> guess)
-> [guess] -> [score] -> [guess]
mkGuesser score strategy dictionary = play dictionary
where
play candidates replies =
let g = strategy candidates
in g : case replies of
[] -> []
r:rs -> play [s | s <- candidates, score s g == r] rsstrategy returns a candidate from its nonempty input. The candidate invariant is exactly the dictionary entries consistent with every score already received. Filtering by score s g == r establishes the same invariant after the next reply and retains the true secret.Crucially, the next guess
g is placed under the outer list constructor before replies is inspected. It depends on earlier replies only; the first guess depends on none. This guarded lazy feedback stream makes the mutually recursive game productive whenever the strategy and scoring operations terminate. Moving the case replies outside the constructor would create a circular demand before the first guess. New to topics? Read the docs here!