The following are exercises 5.10, and 5.11 from the Scheme text "Concrete
Abstractions" by Max Hailperin, et al. The text at that point is about writing
verifiers to check ID numbers such as ISBNs, credit card numbers, UPCs, etc.
======
Exercise 5.10
Write a predicate that takes a number and determines whether the sum of its
digits is divisible by 17.
Exercise 5.11
Write a procedure make-verifier, which takes f and m as its two arguments and
returns a procedure capable of checking a number. The argument f is itself a
procedure of course. Here is a particularly simple example of a verifier being
made and used.
(define check-isbn (make-verifier * 11))
(check-isbn 0262010771)
#t
The value #t is the "true" value; it indicates that the number is a valid ISBN.
As we just saw, for ISBN numbers the divisor is 11 and the function is simply
f(i,d(i)) = i * d(i). Other kinds of numbers use slightly more complicated
functions, but you will still be able to use make-verifier to make a verifier
much more easily than if you had to start from scratch.
=======
Here's the Scheme check-verifier function I wrote, followed by my humble
attempt at a Haskell function that does the same thing. Below that are some
verifier functions created with the Scheme make-verifier. Admittedly, functions
that return functions are Lispy, but perhaps there a Haskelly way to accomplish
the same thing?
Michael
===============
(define (make-verifier f m) ;f is f(i,d) & m is divisor
(lambda (n)
(let* ((d (digits n))
(i (index (length d)))) ;(index 3) => (1 2 3)
(divides? m (reduce + 0 (map f i d)))))) #f
makeVerifier :: (Int -> Int -> Int) -> Int -> (Int -> Bool)
makeVerifier f m = \n -> let d = digits n
i = [1..(length d)]
in \n -> divides m (foldl (+) 0 (map2 f i d))
-- Note: Reduce is just foldl f 0 lst, but map2 is
map2 :: (Int -> Int -> Int) -> [Int] -> [Int] -> [Int]
map2 f m n = [ f i d | (i,d) <- zip m n]
-- And here's my digits function
digits :: Int -> [Int]
digits 0 = []
digits n = rem n 10 : digits (quot n 10)
-- And divides function
divides :: Int -> Int -> Bool
divides divisor n = 0 == rem n divisor
=====
(define check-isbn ;book number
(make-verifier
*
11))
(define check-upc ;universal product code
(make-verifier
(lambda (i d) (if (odd? i) d (* 3 d)))
10))
(define check-cc ;credit card
(make-verifier
(lambda (i d) (if (odd? i) d (if (< d 5) (* 2 d) (+ (* 2 d) 1))))
10))
(define check-usps ;postal money order
(make-verifier
(lambda (i d) (if (= i 1) (- d) d))
9))
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe