Haskell: List Comprehension Combiners

Inspired by this article. I played with translation functions from list comprehension to combinational style. I found something interesting.

-- Example 1: List Comprehension *Main> [x|(x:_)<-["hi","hello",""]] "hh" -- Example 2: Combinatory *Main> map head ["hi","hello",""] "hh*** Exception: Prelude.head: empty list -- Example 3: List Comprehension (translated from Example 2) *Main> [head xs|xs<-["hi","hello",""]] "hh*** Exception: Prelude.head: empty list 

It seems strange that Example 1 does not throw an exception because the pattern (x:_) matches one of the definitions of head . Is there an implied filter (not . null) when using lists?

+8
exception haskell list-comprehension
source share
3 answers

In the Haskell section, see the section on listing contents . So basically

 [x|(x:_)<-["hi","hello",""]] 

translates as

 let ok (x:_) = [ x ] ok _ = [ ] in concatMap ok ["hi","hello",""] 

PS Since list views can be translated into do expressions, a similar situation occurs with do expressions, as described in the section on expressions . So the following result will also give the same result:

 do (x:_)<-["hi","hello",""] return x 
+7
source share

Pattern matching errors are handled specifically for list comprehension. If the pattern does not match, the item is discarded. Therefore, you just get "hh" , but nothing for the third element of the list, since the element does not match the pattern.

This is due to the definition of the fail function, called by the list comprehension, if the template does not correspond to some element:

 fail _ = [] 

The right parts of this answer are courtesy of kmc of #haskell . All my mistakes, do not blame him.

+7
source share

Yes. When you qualify a list comprehension according to a pattern, values ​​that do not match are filtered out to get rid of the empty list in your example 1. In example 3, an empty list matches the xs pattern, so it is not filtered, then head xs fails. Pattern matching point is a safe combination of constructor discrimination with component selection!

You can achieve the same dubious effect with an irrefutable pattern by lazily making choices without discrimination.

 Prelude> [x|(~(x:_))<-["hi","hello",""]] "hh*** Exception: <interactive>:1:0-30: Irrefutable pattern failed for pattern (x : _) 

The enumeration carefully understands the use of map , concat and therefore filter packages.

+6
source share

All Articles