How to rewrite this list in Haskell?

Submitted by metaperl on Fri, 09/29/2006 - 9:51am.

I really miss haskell. But Python is not bad. It's easier to read than Ocaml. Not as fast as OCaml. But many more libraries. Haskell is for people who can think. I never quite made it over the hump with Haskell for some reason.

But anyway, I was wondering what a Haskell solution to this would look like. I'm sure it's just a one-liner making use of concatMap() and a binary decision function that returns a list as a function of it's inputs:


def retokenize(l):
"""Given a list consisting of terms and the negation symbol, retokenize() creates a list which
(1) changes negation symbols to AND NOT and
(2) inserts AND between two terms without an interceding
conjunction symbol. Examples:

>>> sqlgen.retokenize( sqlgen.tokenize("cancer drug").asList() )
['cancer', 'AND', 'drug']
>>> sqlgen.retokenize( sqlgen.tokenize("cancer - drug").asList() )
['cancer', 'AND NOT', 'drug']
>>> sqlgen.retokenize( sqlgen.tokenize("cancer drug therapy").asList() )
['cancer', 'AND', 'drug', 'AND', 'therapy']
>>> sqlgen.retokenize( sqlgen.tokenize("cancer - drug - therapy").asList() )
['cancer', 'AND NOT', 'drug', 'AND NOT', 'therapy']
>>>

"""

o = []
for i, tok in enumerate(l):
if tok == neg:
o.append('AND NOT')
else:
if i == 0:
o.append(tok)
elif l[i-1] == neg:
o.append(tok)
else:
o.append('AND')
o.append(tok)

return o

I know my eyes are going to water when I see that elegant, purefuly functional solution :)

Submitted by jrn on Fri, 09/29/2006 - 3:35pm.

I doubt this is the elegant solution you are looking for :)

-- stagger [a,b,c,d,e] = [(a,b), (b,c), (c,d), (d,e)]
-- so: map snd $ stagger xs == tail xs
-- map fst $ stagger xs == init xs
stagger :: [a] -> [(a,a)]
stagger precs@(x:xs) = zip precs xs

verbalize :: (String, String) -> [String]
verbalize ("-","-") = error "Double negative"
verbalize ("-",s) = ["AND NOT", s]
verbalize (_, "-") = [] -- FIXME: ignores final -
verbalize (_, s) = ["AND", s]

retokenize :: [String] -> [String]
retokenize [] = error "Empty list"
retokenize ("-":_) = error "Begins with -"
retokenize xs@(h:_) = [h] ++ concatMap verbalize (stagger xs)

Submitted by ithika on Thu, 10/05/2006 - 5:45pm.

I wrote this one out at work so I'm not 100% sure if I remember it correctly. I'll post later if I realise my mistake. But it went something like this:


import Data.List

retokenise :: String -> String
retokenise = unwords . intersperse "AND NOT"
	. map (unwords . intersperse "AND")
	. breakRun "-" . words

breakRun :: Eq a => a -> [a] -> [[a]]
breakRun _ [] = []
breakRun p l =
	let
		(h,rem) = break (p==) l
		l' = dropWhile (p==) rem
	in h : breakRun p l'

I think there's a function a bit like breakRun in the MissingH package. So if you assume that, then yes, it's a one-liner! :)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.