2
votes

The aim of this exercise is to take a list of String and and construct a list of Char, in other words, given a the below list a string

function input

let input = ["c", "cac", "cb", "bcc", "ba"]

applying some behavior

zip' xs = zip xs (tail xs)
let res1 =zip' input

after zipping each element in the (input) list with the rest of the list, i will get a list of tuple as per the below

print res1
res1 =  [("c","cac"),("cac","cb"),("cb","bcc"),("bcc","ba")]

applying some other behavior on res1

zip''  = \(a,b)->zip a b
let res2 = zip'' res1

zipping the first and the second item of each pair in the list will get the below list

 print res2
    res2 = [[('c','c')],[('c','c'),('a','b')],[('c','b'),('b','c')],[('b','b'),('c','a')]]

applying some other behavior on res2

let finalRes = concat res2

output

print finalRes
finalRes= [('c','c'),('c','c'),('a','b'),('c','b'),('b','c'),('b','b'),('c','a')]

NOW THE MONADIC STYLE

this problem is obvious to solve it without monad, while I am new to monad and trying to understand it, I have made an attempt to solve it using the bind function >>=, I wrote 2 function and bind it together in order to get from ** input ** to output :

zip':: [String] -> [(String,String)]
zip' xs = zip xs (tail xs)

and

zip'' :: ([a], [b]) -> [(a, b)]
zip''  = \(a,b)->zip a b

then

ff =zip'' >>= zip'

while compiling the code I got an error in the function ff that type do not align.

let me re-write the bind signature

Monad m => m a -> (a -> m b) -> m b

applying ff ["c", "cac", "cb", "bcc", "ba"]

as I have understood, that the zip' takes a list of String and return a list of pair which is a context of pair so it is the first argument m a for the bind operator which shouhld align with the second function zip''. so the function zip'' will take each pair/tuple and apply its behavior in order to return the concatenated list of Char.

what Have I miss , and what is wrong in the code?

sorry for the long question

1
It is difficult to determine what you are trying to achieve. Could you rephrase your question, such that it is clear what you are trying to achieve? Maybe even just an example input with an associated desired output?Undreren
thanks for your interest, hope it is clear nowkhaled omar
zip'' takes a (String, String) argument, but res1 :: [(String, String)]. You would have to run map zip'' res1 to get the res2 that you show.chepner
zip', by the way, can be written more succinctly as zip <*> tail.chepner

1 Answers

3
votes

Your ff function is backwards. You should start with zip' and bind to zip'' like this:

ff list = zip' list >>= zip''

Running it through the REPL gives you:

> let zip' xs = zip xs (tail xs)
> let zip'' = \(a,b)->zip a b
> let ff list = zip' list >>= zip''
> ff ["c", "cac", "cb", "bcc", "ba"]
[('c','c'),('c','c'),('a','b'),('c','b'),('b','c'),('b','b'),('c','a')]