Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering list of tuples with isPrefixOf

Tags:

haskell

I am in need of a function, which can do the following:

prefixes :: String -> [String] -> [(Int,String)]
prefixes "apples" ["ap","appl","le"] == [(0, "ap"), (1, "appl")] :: [(Int, String)]

So far I have managed to make this:

prefixes xs (y:ys) = filter ((isPrefixOf xs).snd) a where
a=(zip [0..] (y:ys))

But the result of this is an empty list, and I can not figure out a way to make it work. (Yes, this was a homework, which I failed to complete on time, but I am still curious about the way to do it properly)

like image 905
Steven P. Avatar asked Nov 29 '11 09:11

Steven P.


1 Answers

The naming of isPrefixOf can be slightly confusing at times, as it's intended to be used infix with backticks, e.g.

> "ap" `isPrefixOf` "apples"
True

However, this means that when we write it without the backticks, the argument order is

isPrefixOf "ap" "apples"

so the partial application isPrefixOf xs is the function that checks if xs is a prefix of its argument, not the other way round. This is why you get an empty list, as you're checking if "apples" is a prefix of any of the shorter strings, which obviously returns False for all of them.

There are three simple ways of fixing this. One is to use flip, which swaps the order of the arguments for a two-parameter function:

flip isPrefixOf xs

The second is to use backticks in an operator section:

(`isPrefixOf` xs)

The third is to be explicit and use a lambda:

\y -> y `isPrefixOf` xs 
like image 66
hammar Avatar answered Oct 21 '22 09:10

hammar