nobody
nobody

Reputation: 2759

Haskell iterate over a list

I know you suppose to think differently in Haskell, but can someone give me a quick answer on how to iterate over a list or nested list and print out a character based on the value of the list element.

list1 = [[1 0 0][0 1 0][0 0 1]]

By iterate through this nested list, it should print out x for 0 and y for 1

yxx
xyx
xxy

Thanks

Upvotes: 3

Views: 33964

Answers (7)

jmejia
jmejia

Reputation: 21

The solutions

cambiar = putStr.unlines.(map (map f)) where f x = if x == 0 then 'x' else 'y'

Upvotes: -1

Zopa
Zopa

Reputation: 668

The solutions using map are the preferred Haskell style. But while you're learning, you may find explicit recursion easier to follow. Like so:

charSub :: Int -> Char
charSub 0 = 'x'
charSub 1 = 'y'
charSub x = error "Non-binary value!"

listSub :: [Int] -> String
listSub [] = []
listSub (x:xs) = (charSub x) : (listSub xs)

nestedSub :: [[Int]] -> String
nestedSub [] = []
nestedSub (y:ys) = (listSub y) ++ "\n" ++ (nestedSub ys) 

map does pretty much the same thing--it applies a function to each element in a list. But it may be easier to see what's going on here.

Upvotes: 2

franza
franza

Reputation: 2327

Try this:

fun :: [[Int]] -> [String]
fun = (map . map) (\x -> if x == 0 then 'x' else 'y')

If you really need printing of result:

printSomeFancyList :: [[Int]] -> IO ()
printSomeFancyList = putStrLn . unlines . fun

Upvotes: 3

Satvik
Satvik

Reputation: 11218

iterateList = foldl1 (>>).concat.intersperse [putStrLn ""].(map.map) (\c ->  putStr $ if (c==0) then "X" else "Y")

Upvotes: 1

MarcoS
MarcoS

Reputation: 13574

If you are interested in arbitrary nested lists, then you can write something like this (an arbitrary nested list is essentially a tree):

data Nested a = Leaf a | Nest [Nested a] deriving Show

traverse :: Nested Integer -> Nested Char
traverse (Leaf x) = Leaf (valueOf x)
traverse (Nest xs) = Nest (map traverse xs)

valueOf :: Integer -> Char
valueOf 0 = 'x'
valueOf 1 = 'y'
valueOf _ = 'z'

With that you can do:

Main> let nl = Nest [Leaf 1, Leaf 0, Nest [Leaf 0, Leaf 0, Leaf 1, Nest [Leaf 1, Leaf 1, Leaf 0]], Nest [Leaf 1, Leaf 1]]
Main> traverse nl
Nest [Leaf 'y',Leaf 'x',Nest [Leaf 'x',Leaf 'x',Leaf 'y',Nest [Leaf 'y',Leaf 'y',Leaf 'x']],Nest [Leaf 'y',Leaf 'y']]

The function traverse takes an arbitrary nested list of Integers and returns a corresponding nested list of Chars according to the valueOf rule

Upvotes: 1

Random Dev
Random Dev

Reputation: 52300

define f by something like

f x = if x == 0 then 'x' else 'y'

then

map (map f) [[1,0,0],[0,1,0],[0,0,1]]

is what you want or if you want it fancier:

map' = map.map
map' f [[1,0,0],[0,1,0],[0,0,1]]

Upvotes: 2

ivanm
ivanm

Reputation: 3927

First of all, I think you mean:

list1 :: [[Int]]
list1 = [[1,0,0],[0,1,0],[0,0,1]]

As for what you want:

valueOf :: Int -> Char
valueOf 0 = 'x'
valueOf 1 = 'y'
valueOf _ = 'z'

listValues :: [[Int]] -> [String]
listValues = map (map valueOf)

printValues :: [[Int]] -> IO ()
printValues = putStrLn . unlines . listValues

And then in ghci:

*Main> printValues list1 
yxx
xyx
xxy

Upvotes: 17

Related Questions