{-  Exploring Languages with Interprters and Functional Programming
    Chapter 18: Higher-Order Function Examples
    Copyright (C) 2018, H. Conrad Cunningham

1234567890123456789012345678901234567890123456789012345678901234567890

2018-08-06: Reconstructed for 2018 textbook Chapter 18

-}

module MoreLists
where

    -- Sequences
    s1  = [1..5]     -- [1,2,3,4,5]
    s2  = [5..1]     -- []  COMPILER WARNING
    s3  = [1,3..9]   -- [1,3,5,7,9]
    s4  = [9,8..5]   -- [9,8,7,6,5]
    s5  = [9,8..11]  -- []  COMPILER WARNING
    s6  = [1..]      -- [1,1,1,...]

    geometric :: (Ord a, Num a) => a -> a -> a -> [a]
    geometric r m n | m > n     = []
                    | otherwise = m : geometric r (m*r) n

    g1  = geometric 2 1 10  -- [1,2,4,8]

    -- List Comprehensions

    c1 n = [ n*n | n <- [1..5]]  -- [1,4,9,16,25]
    c2 n = [ n*n | even n ]      -- (if even n then [n*n] else [])
    c3   = [ n*n | let n = 2 ]   -- [4]


    c4  = [ (m,n) | m<-[1..3], n<-[4,5] ]
    -- [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]

    c5  = [ n*n | n<-[1..10], even n ]  -- [4,16,36,64,100]
    c6  = [ (m,n) | m<-[1..3], n<-[1..m] ]
    -- [ (1,1), (2,1), (2,2), (3,1), (3,2), (3,3)]

    c7  = [ 27 | n<-[1..3]]            -- [27,27,27]
    c8  = [ x | x<-[1..3], y<-[1..2]]  -- [1,1,2,2,3,3]
   
    -- Strings of Spaces

    spaces :: Int -> String
    spaces n = [ ' ' | i<-[1..n]]

    -- Prime number test

    isPrime :: Int -> Bool
    isPrime n | n > 1 = (factors n == [])
        where factors m = [ x | x<-[2..(m-1)], m `mod` x == 0 ]
    isPrime   _       =  False

    -- Squares of primes

    sqPrimes :: Int -> Int -> [Int]
    sqPrimes m n = [ x*x | x<-[m..n], isPrime x ]

    sqPrimes' :: Int -> Int -> [Int]
    sqPrimes' m n = map (\x -> x*x) (filter isPrime [m..n])

    -- Doubling positive elements

    doublePos5 :: [Int] -> [Int]
    doublePos5 xs = [ 2*x | x<-xs, 0 < x ]

    -- Concatenating a list of lists of lists

    superConcat :: [[[a]]] -> [a]
    superConcat xsss = [ x | xss<-xsss, xs<-xss, x<-xs ]

    superConcat' :: [[[a]]] -> [a]
    superConcat' = concat . map concat

    -- First occurrence in a list 

    positions :: Eq a => [a] -> a -> [Int]
    positions xs x = [ i | (i,y)<-zip [1..length xs] xs, x == y]

    position :: Eq a => [a] -> a -> Int 
    position xs x = head ( positions xs x ++ [0] )

