Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Going through SICP in Haskell

Name: Anonymous 2010-03-26 11:27

I've been going through SICP, first in Scheme and then in Haskell, and I started wondering...

Is my Haskell too Lisp-y?

filterAccumulate
    :: (Eq t1) =>
       (t1 -> Bool) -> (t2 -> t3 -> t3) -> t3 -> (t1 -> t2) -> t1 -> (t1 -> t1) -> t1 -> t3
filterAccumulate filter combiner nullVal term a next b =
    iter a nullVal
    where
    iter a result =
        if (a == b) then filterCombiner a result
        else iter (next a) (filterCombiner a result)
    filterCombiner a result =
        if (filter a) then combiner (term a) result
        else result

Name: Anonymous 2010-03-26 11:35

Yes, good trolling good sir

Name: Anonymous 2010-03-26 11:39


NO EXCEPTIONS

Name: Anonymous 2010-03-26 11:55

Incidentally, I have been writing Haskelly Scheme recently. Monads and type signatures everywhere :(

Name: Anonymous 2010-03-26 12:28

fuck you

Name: Anonymous 2010-03-26 12:42

>>4
I've started using type signatures in Scheme as well. Even if they don't act as constraints, they can clear things up a bit. But I wouldn't even know how to start using monadic idioms in Scheme.

Anyway, maybe this soothes the Haskell soul a bit:
myAccumulate = filterAccumulate (const True)

I also decided to do the rational numbers.
-- Section 2.1.1
makeRational n d =
    (n2 `div` g, d2 `div` g)
    where
    g = gcd n d
    n2 = (abs n) * (sign $ n `div` d)
    d2 = abs d
    sign n | (n < 0) = -1
           | otherwise = 1

numerator = fst

denominator = snd

addRational x y =
    makeRational ((cm x y) + (cm y x))
                 (((*) `on` denominator) x y)
    where cm a b = (numerator a) * (denominator b)

showRational r = do
    putStrLn ((show $ numerator r) ++ "/" ++ (show $ denominator r))

Name: Anonymous 2010-03-26 14:26

SICP's crazy fucked-up method of cons-ing counting numbers:

cons a b = (2^a)*(3^b)
car = fromCounting 2
cdr = fromCounting 3
fromCounting t p =
    iter 0 p
    where
    iter a p = if r /= 0 then a
               else iter (a+1) q
               where (q,r) = p `divMod` t


let foo = cons 1 4
foo
foo
162
car foo
1
cdr foo
4
let bar = cons 5 foo
bar
bar
6292065615217693235778429072861187721059310430214872541674093297214924518297888
car bar
5
car (cdr bar)
1
cdr (cdr bar)
4

Just blew my fuckin' mind. I'm referring, of course, to Haskell's handling of large numbers. PLT Scheme would have had an aneurysm.

Name: Anonymous 2010-03-26 15:08

>>7
PLT Scheme would have had an aneurysm.
HIBT? My naive translation works fine in PLT, and in Ikarus if I change (require srfi/8 srfi/26) to (import (srfi :8) (srfi :26)) and (define quotient/remainder div-and-mod). Scheme's numeric tower has been excellent for a long time. R5RS says
Implementations are encouraged, but not required, to support exact integers and exact rationals of practically  unlimited size and precision, but I believe R6RS made it a hard requirement. I found out when plotting some Julia sets that PLT even supports unlimited size and precision for complex numbers which meant I had to force it do inexact arithmetic to speed things up :)
(require srfi/8 srfi/26)
(define (cons a b)
  (* (expt 2 a)
     (expt 3 b)))
(define (fromCounting t p)
  (let iter ((a 0) (p p))
    (receive (q r) (quotient/remainder p t)
             (if (zero? r)
                 (iter (add1 a) q)
                 a))))
(define car (cut fromCounting 2 <>))
(define cdr (cut fromCounting 3 <>))

(define foo (cons 1 4))
(list foo (car foo) (cdr foo))

(define bar (cons 5 foo))
(list bar (car bar) (car (cdr bar)) (cdr (cdr bar)))

Name: Anonymous 2010-03-26 15:14

>>8
I should say probably say what those SRFIs are.
SRFI 8 is receive, which is just a macro around call-with-values. IIRC R6RS standardised let-values, but that looks ugly when you want to get the values of one expression, which, for me anyway, is the common case.
SRFI 26 provides cut and cute which are just macros for specialising functions. It works out much nicer than having to explicitly write the lambdas or currying you scheme code.

Name: Anonymous 2010-03-26 15:24

Real programmers can programm FORTRAN in ever language.
-> only way to fix lisp and haskell.

Name: Anonymous 2010-03-26 15:29

>>8
I defined it a little differently, and it may in fact be buggy.

(define (from-counting-pair t p)
  (define (iter a p)
    (if (= (remainder p t) 0)
        (iter (+ a 1) (quotient p t))
        a))
  (iter 0 p))


At the very least it's less efficient because it does remainder and quotient separately. I didn't know that there is a pattern matching form receive in Scheme.

Name: Anonymous 2010-03-26 15:29

>>10
FWIW, that's not how I would have written the scheme code, I was trying to give a faithful translation of >>7.

Name: Anonymous 2010-03-26 15:30

>>9
>>11
BTW YHNBT

Name: Anonymous 2010-03-26 15:32

>>12
Yes you did and the chaos escaped from the eve.

Name: Anonymous 2010-03-26 21:31

C / Perl / occasional Lisp programmer here. Am I the only person who doesn't get the fucking point of Haskell? True, I have little knowledge of the underlying syntax of the language, but from various discussions I've read here and on /code/, I just don't understand how in the hell a Haskell program is supposed to resemble a computer program. I can programs made in various languages, even Lisp, and easily recognize after a few seconds ``oh, that's what it does. I'm guessing when translated/compiled it would look something like blah blah blah.'' When I try to make any kind of sense out of a Haskell program, I feel like I'm trying to program on a mushroom.

Name: Anonymous 2010-03-26 22:05

>>15
I think if you add Erlang to your list you'll quickly see the point of Haskell. This is what I've been told anyway, when I asked for another Erlang. (Don't get me wrong, Erlang is dandy.)

Name: Anonymous 2010-03-26 22:45

>>15
Haskell lets you represent programs more clearly and beautifully than any other language. Then it goes beyond that and lets you represent them in a more obfuscated and incomprehensible fashion than any other language, while still retaining the fundamental beauty and simplicity.

Name: Anonymous 2010-03-27 1:44

>>15
If you don't understand what Haskell is up to, you don't know Lisp well enough. Unless the part you don't get is why all the syntax. That's just because Haskeller's are nuts.

Name: Anonymous 2010-03-27 11:40

>>18

import Data.Function in every program.

Name: Anonymous 2010-09-02 19:45

Name: Anonymous 2010-09-02 19:55

>>20
In the time it took you to find this thread you could have read them and found out already.

Name: Anonymous 2010-09-03 18:00

>>18
+1

Name: Anonymous 2010-09-06 13:19

>>18
What about Haskeller is are nuts?

Name: Anonymous 2010-11-27 11:59

Name: Anonymous 2010-12-17 1:36

Are you GAY?
Are you a NIGGER?
Are you a GAY NIGGER?

If you answered "Yes" to all of the above questions, then GNAA (GAY NIGGER ASSOCIATION OF AMERICA) might be exactly what you've been looking for!

Name: Anonymous 2010-12-23 6:49

Name: necromancy 2011-01-22 20:12

I love fucking dead threads

Name: Anonymous 2011-01-22 20:26

I love fucking dead dogs

Name: Anonymous 2011-01-22 20:35

>>28
U MENA HASKAL

Name: Anonymous 2011-01-22 20:43

>>27,28-29
Go away.

Name: Anonymous 2011-01-22 20:57

>>30
OPTIMIZE YO'URE QUOTES PLEASE

Name: Anonymous 2011-01-22 20:59

>>30
nice.

Name: Anonymous 2011-01-22 20:59

>>30
I lol'd

Name: Anonymous 2011-01-22 21:36

FUCK OFF SPAMMER

Name: Anonymous 2011-01-22 21:54

>>34
nice.

Name: Anonymous 2011-01-22 21:56

>>34
I lol'd

Name: Anonymous 2011-01-23 4:36

>>36
hahahaha, I lol'd TOOO. so random xD

Name: Anonymous 2011-01-23 11:43

>>36
hahahaha, TOOO nice. so random xD

Name: Anonymous 2011-01-23 12:23

>>1
too Lisp-y
there's no such thing

Name: Anonymous 2011-01-23 12:39

YHBT

Name: Anonymous 2011-01-23 12:40

YHBT

Name: Anonymous 2011-01-23 12:41

YHBT

Name: Anonymous 2011-01-23 12:42

YHBT

Name: Anonymous 2011-01-23 12:42

YHBT

Name: Anonymous 2011-01-23 12:43

YHBT

Name: Anonymous 2011-01-23 12:44

YHBT

Name: Anonymous 2011-01-23 12:45

YHBT

Name: Anonymous 2011-01-23 12:46

YHBT

Name: Anonymous 2011-01-23 12:47

YHBT

Name: Anonymous 2011-01-23 12:48

YHBT

Name: Anonymous 2011-01-23 12:49

YHBT

Name: Anonymous 2011-01-23 12:50

YHBT

Name: Anonymous 2011-01-23 12:51

YHBT

Name: Anonymous 2011-01-23 12:52

YHBT

Name: Anonymous 2011-01-23 12:53

YHBT

Name: Anonymous 2011-01-23 12:54

YHBT

Name: Anonymous 2011-01-23 12:54

YHBT

Name: Anonymous 2011-01-23 12:55

YHBT

Name: Anonymous 2011-01-23 12:56

YHBT

Name: Anonymous 2011-01-23 12:57

YHBT

Name: Anonymous 2011-01-23 12:58

YHBT

Name: Anonymous 2011-01-23 12:59

YHBT

Name: Anonymous 2011-01-23 13:00

YHBT

Name: Anonymous 2011-01-23 13:01

YHBT

Name: Anonymous 2011-01-23 13:02

YHBT

Name: Anonymous 2011-01-23 13:03

YHBT

Name: Anonymous 2011-01-23 13:04

YHBT

Name: Anonymous 2011-01-23 13:05

YHBT

Name: Anonymous 2011-01-23 13:06

YHBT

Name: Anonymous 2011-01-23 13:06

YHBT

Name: Anonymous 2011-01-23 19:16

>>18
Syntactic sugar is sweet. If you find that it's too sweet for your taste, you may as well return to Scheme.

Name: Anonymous 2011-01-24 10:16

>>1
derp

Name: Anonymous 2013-09-15 17:15

>>1

Looking at your code I made first a little rewrite to make your type more recognizable, then I recognized, what it actually did.

So what you are actually doing is the following pipeline:

fold . filter . unfold

This code can be much neater written like this:


import Data.List
import Test.QuickCheck
import Text.Show.Fu
unfoldy :: (t1 -> Maybe t1) -> t1 -> [t1]
unfoldy f  s = s : unfoldr (fmap (\x -> (x,x)) . f) s  

filterAccumulate' :: (s -> Bool) -> (b -> s -> b) -> b -> (s -> Maybe s) -> s -> b
filterAccumulate' pred f z g  = foldl' f z . filter pred . unfoldy g


I recognize you are actually fusing together two functions. So you can change the pipeline to :

unfoldr . foldr


filterAccumulate'' :: (b -> s -> b) -> b -> (s -> Maybe s) -> s -> b
filterAccumulate'' f z g = foldl' f z . unfoldy g



For test if the function behave the same:


prop_same = property (forAll (suchThat arbitrary (uncurry (<))) $ \(b,e) ->
                        forAll (elements [even, odd, (>10), (<10)]) $ \f -> sameThree $ test_same f b e)
                       

sameThree :: Eq a => (a,a,a) -> Bool
sameThree (a,b,c) = a == b && b == c

test_same :: (Int -> Bool) -> Int -> Int -> ([String], [String], [String])
test_same f b e = (filterAccumulate f b succ e show (:) [], filterAccumulate' f step [] next b, filterAccumulate'' step' [] next b)
        where step z x = show x : z
              next x | x < e = Just (succ x)
                     | otherwise = Nothing
              step' z x | f x = show x : z
                        | otherwise = z



As kicker you can also write it as an hylomorphism, but I am starting to lose my interest. But to cut some trees for you in the forest, so you can see the actual forest (haha), I give you this:



hylo e g = e . fmap (hylo e g) . g

filterAccumulateHylo = hylo step next 
    where step (a,b) | even a = show a : b
                     | otherwise = b
          next a = (succ a, succ a)


Which generates an infinite list:


take 10 $ filterAccumulateHylo


If you can write it as an hylomorphism, your code will be short and efficient.

Don't change these.
Name: Email:
Entire Thread Thread List