<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;">Cool. I expected as much.<br><br>My ISP seems to be swamped (Easter?) so maybe more later after I look at your remarks.<br><br>Thanks.<br><br>Michael<br><br>--- On <b>Sun, 4/12/09, Daniel Fischer <i><daniel.is.fischer@web.de></i></b> wrote:<br><blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"><br>From: Daniel Fischer <daniel.is.fischer@web.de><br>Subject: Re: [Haskell-cafe] Functions that return functions<br>To: haskell-cafe@haskell.org<br>Cc: "michael rice" <nowgate@yahoo.com><br>Date: Sunday, April 12, 2009, 12:15 PM<br><br><div class="plainMail">Am Sonntag 12 April 2009 17:38:53 schrieb michael rice:<br>> The following are exercises 5.10, and 5.11 from the Scheme text "Concrete<br>> Abstractions" by Max Hailperin, et al. The text at that point is about<br>> writing verifiers to check
ID numbers such as ISBNs, credit card numbers,<br>> UPCs, etc.<br>><br>> ======<br>><br>> Exercise 5.10<br>> Write a predicate that takes a number and determines whether the sum of its<br>> digits is divisible by 17.<br>><br>> Exercise 5.11<br>> Write a procedure make-verifier, which takes f and m as its two arguments<br>> and returns a procedure capable of checking a number. The argument f is<br>> itself a procedure of course. Here is a particularly simple example of a<br>> verifier being made and used.<br>><br>> (define check-isbn (make-verifier * 11))<br>><br>> (check-isbn 0262010771)<br>> #t<br>><br>> The value #t is the "true" value; it indicates that the number is a valid<br>> ISBN.<br>><br>> As we just saw, for ISBN numbers the divisor is 11 and the function is<br>> simply f(i,d(i)) = i * d(i). Other kinds of numbers use slightly more<br>> complicated functions, but you
will still be able to use make-verifier to<br>> make a verifier much more easily than if you had to start from scratch.<br>><br>> =======<br>><br>> Here's the Scheme check-verifier function I wrote, followed by my humble<br>> attempt at a Haskell function that does the same thing. Below that are some<br>> verifier functions created with the Scheme make-verifier. Admittedly,<br>> functions that return functions are Lispy, but perhaps there a Haskelly way<br>> to accomplish the same thing?<br><br>Functions returning functions are quite natural in Haskell.<br>Since usually functions are written in curried form, a function returng a function <br>corresponds to a function of multiple arguments applied to only some of them.<br><br>><br>> Michael<br>><br>> =============== <br>><br>><br>> (define (make-verifier f m) ;f is f(i,d) & m is divisor<br>> (lambda (n)<br>> (let*
((d (digits n))<br>> (i (index (length d)))) ;(index 3) => (1 2 3)<br>> (divides? m (reduce + 0 (map f i d)))))) #f<br>><br>> makeVerifier :: (Int -> Int -> Int) -> Int -> (Int -> Bool)<br>><br>> makeVerifier f m = \n -> let d = digits n<br>><br>> i = [1..(length d)]<br>><br>> in \n -> divides m (foldl (+) 0 (map2 f i d))<br>><br>><br><br>makeVerifier f m n = divides m . foldl (+) 0 $ zipWith f [1 .. ] (digits n)<br><br>just call makeVerifier f m to get your verification function :)<br><br>If you don't want
to name the last argument:<br><br>makeVerifier f m = divides m . foldl (+) 0 . zipWith f [1 .. ] . digits<br><br>more point-freeing would be obfuscation.<br>Instead of foldl (+) 0, you could also just write sum.<br><br>><br>> -- Note: Reduce is just foldl f 0 lst, but map2 is<br>> map2 :: (Int -> Int -> Int) -> [Int] -> [Int] -> [Int]<br>> map2 f m n = [ f i d | (i,d) <- zip m n]<br><br>map2 is zipWith, already in the Prelude.<br><br>><br>> -- And here's my digits function<br>> digits :: Int -> [Int]<br>> digits 0 = []<br>> digits n = rem n 10 : digits (quot n 10)<br><br>Unless you are desperate for speed and sure you deal only with positive numbers (or know <br>that you really want quot and rem), better use div and mod. Those give the commonly <br>expected (unless your expectation has been ruined by the behaviour of % in C, Java...) <br>results.<br><br>><br>> -- And divides function<br>> divides
:: Int -> Int -> Bool<br>> divides divisor n = 0 == rem n divisor<br>><br>> =====<br>><br>> (define check-isbn ;book number<br>> (make-verifier<br>> *<br>> 11))<br>><br>> (define check-upc ;universal product code<br>> (make-verifier<br>> (lambda (i d) (if (odd? i) d (* 3 d)))<br>> 10))<br>><br>> (define check-cc ;credit card<br>> (make-verifier<br>> (lambda (i d) (if (odd? i) d (if (< d 5) (* 2 d) (+ (* 2 d) 1))))<br>> 10))<br>><br>> (define check-usps ;postal money order<br>> (make-verifier<br>> (lambda (i d) (if (= i 1) (- d) d))<br>> 9))<br><br></div></blockquote></td></tr></table><br>