import Prelude hiding   ( map, filter
                        , zip, zipWith
                        )
import Data.List        ( tails
                        , isPrefixOf
                        )
import Data.Maybe       ( listToMaybe
                        )
 
 
allOcc        :: Eq a => [a] -> [a] -> [Int]
firstOcc      :: Eq a => [a] -> [a] -> Maybe Int
lastOcc       :: Eq a => [a] -> [a] -> Maybe Int
isSubstringOf :: Eq a => [a] -> [a] -> Bool
 
allOcc x
    = map fst
      . filter (isPrefixOf x . snd)
      . zip [0..]
      . tails
 
firstOcc x
    = listToMaybe . allOcc x
 
lastOcc x
    = listToMaybe . reverse . allOcc x
 
isSubstringOf x
    = not . null . allOcc x
 
 
map          :: (a -> b) -> ([a] -> [b])
map f []     = []
map f (x:xs) = f x : map f xs
 
 
filter            :: (a -> Bool) -> [a] -> [a]
filter p []       = []
filter p (x:xs)
    | p x         = x : filter p xs
    | otherwise   =     filter p xs
 
 
zip               :: [a] -> [b] -> [(a, b)]
zip []     _      = []
zip _      []     = []
zip (x:xs) (y:ys) = (x,y) : zip xs ys
 
zipWith           :: (a -> b -> c) -> ([a] -> [b] -> [c])
zipWith op [] _   = []
zipWith op _ []   = []
zipWith op (x:xs) (y:ys)
                  = op x y : zipWith op xs ys
 
 
test1 = allOcc   "aba" "123ababac"
test2 = firstOcc "aba" "123ababac"
test3 = lastOcc  "aba" "123ababac"
test4 = "aba" `isSubstringOf` "123ababac"
test5 = firstOcc "abc" "123ababac"