[Haskell-beginners] Simplifying code

edgar klerks edgar.klerks at gmail.com
Tue Feb 9 15:11:55 EST 2010


Hi All,

I wrote a program which permutates a list words with some rules. For example
if I feed it a list like:

banana
waterloo
vraag

It gives back the list:

banana
b at nana
ban at na
b at n@na
banan@
b at nan@
ban at n@
b at n@n@
waterloo
wa+erloo
water|oo
waterl0o
etc

However I have the feeling I am doing things to complicated. I am still a
beginner. Would someone like to help me simplify somethings. If you think
this is inappropriate please state also. I am not offended then. I
understand you are offering your spare time to help me.

The first thing I don't get is this. I recognize some things could be
rewritten with a bind operator (because of the concat $ fmap), but I am
puzzled how:

mutateWords :: [Char] -> [[Char]]
mutateWords word = nub.concat $ fmap snd <$> fmap unzip <$> ( foldr(\x z ->

                        let char = snd x
                            nm = number word
                            lst = fst x
                        in (insertAt char nm <$> lst) : z
                ) [[]] $ mw word )




Here is the full code:


import Data.List
import System
import System.IO
import Control.Applicative


---CONFIG section

leat = ['s' ==> '$', 't' ==> '+', 'l' ==> '|', 'o' ==> '0','e' ==> '3', 'a'
==> '@', 'v' ==> '^']

leata = fst.unzip $ leat
leatb = snd.unzip $ leat

-- Perl like assoc lists
infixl 1 ==>
a ==> b = (a, b)


-- Flipped fmap sometimes nicer
infixl 4 <$$>

xs <$$> f = f <$> xs


-- first I need to find  the positions of the mutatable charachters.
findPositions :: [Char] -> [[Int]]
findPositions xs = take (length index) $ index <*> [xs]
        where index = elemIndices <$> leata

-- And generate all subsequences
findSubSeq :: [Char] -> [[[Int]]]
findSubSeq  = fmap subsequences <$> findPositions


-- Only change elements which needs to be changed
insertAt :: Char -> [(Int, Char)] -> [Int] -> [(Int,Char)]
insertAt c xs ps = xs <$$> (\x ->
                if (fst x) `elem` ps
                        then (fst x , c)
                        else x
                )
-- Couples character to mutable positions
mw word = (findSubSeq word) `zip` leatb

number = zip [0..]

mutateWords :: [Char] -> [[Char]]
mutateWords word = nub.concat $ fmap snd <$> fmap unzip <$> ( foldr(\x z ->

                        let char = snd x
                            nm = number word
                            lst = fst x
                        in (insertAt char nm <$> lst) : z
                ) [[]] $ mw word )

generateAll :: [Char] -> [[Char]]
generateAll word = g lea $ mutateWords word
    where   g 0 words = words
                g n words = g (n - 1) (nub  $  words >>= mutateWords )
                lea = length leata
main = do
        filename <- getArgs
        wordlist <- readFile $ filename !! 0
        let a = (words wordlist) >>= generateAll
        mapM_ putStrLn  a

-- 
Flatliner ICT Service,
Email: Edgar.klerks at gmail.com,
Tel: +31727851429
Fax: +31848363080
Skype: edgar.klerks
Website: flatlinerict.nl
Adres: Koelmalaan 258,
1813JD, Alkmaar
Nederland
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20100209/363c8357/attachment-0001.html


More information about the Beginners mailing list