By enabling XTransformListComp extension,
we can further enhance list comprehensions and perform operations such as
sorting and grouping which are familiar from SQL.
How
to enable XTransformListComp?
:set –XTransformListComp
Run above command in GHCi to enable
XTransformListComp.
After enabling the GHCi extension, you
can use the keyword then to enhance list comprehensions. Following are the
different forms of then keyword.
1.
then f
2.
then f by e
3.
then group by e using f
4.
then group using f
then f
This
statement requires that f have the type forall a. [a] -> [a]
Prelude> :set -XTransformListComp Prelude> [x^2 | x <- [1, 5, -3, 4, 8, -10], then reverse] [100,64,16,9,25,1]
Examples
1.
Square every element of list and then reverse
ListUtil.hs
{-# LANGUAGE TransformListComp #-} squareReverse :: [Integer] -> [Integer] squareReverse list = [x^2 | x <- list, then reverse]
Prelude> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> squareReverse [1, -2, 8, -6] [36,64,4,1]
then f by e
This is similar to then statement, but allows you to
create a function which will be passed as the first argument to f.. This
statement requires that f have the type (a -> t) -> [a] -> [a].
1. Square every element of list and then sort
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts squareSort :: [Integer] -> [Integer] squareSort list = [x^2 | x <- list, then sortWith by x^2]
Prelude> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> squareSort [1, -2, 10, -8, 3, 5] [1,4,9,25,64,100]
2. Sort
elements of list of string by their length.
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts sortList :: [String] -> [String] sortList list = [x | x <- list, then sortWith by (length x)]
Prelude> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> sortList ["Hari", "Krishna", "PTR", "Nayan"] ["PTR","Hari","Nayan","Krishna"] *Main>
then group by e using f
By using above
statement we can perform grouping operations. In this form, f is required to
have type forall a. (a -> t) -> [a] -> [[a]].
1. Group list of names using their length
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts processInfo list = [ (the len, name) | name <- list, let len = length name, then group by len using groupWith ]
Prelude> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> processInfo ["Hari", "Krishna", "PTR", "Nayan", "Rama", "Gopi", "Sudheer"] [(3,["PTR"]),(4,["Hari","Rama","Gopi"]),(5,["Nayan"]),(7,["Krishna","Sudheer"])] *Main>
Rerun List
Util.hs by removing the keyword ‘the’, you will get following output.
*Main> processInfo ["Hari", "Krishna", "PTR", "Nayan", "Rama", "Gopi", "Sudheer"] [([3],["PTR"]),([4,4,4],["Hari","Rama","Gopi"]),([5],["Nayan"]),([7,7],["Krishna","Sudheer"])]
‘the’ function
to change the type of length of names from a list to its original numeric type.
*Main> :t the the :: Eq a => [a] -> a *Main> *Main> the [1, 1, 1] 1 *Main> the ["abc", "abc", "abc"] "abc"
2. Given a list of tuples like this:
dic =
[(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")]
Group hem by using first element of every tuple.
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts import Data.List import Data.Function (on) process :: [(Integer, String)] -> [(Integer, [String])] process list = [ (the x, y) | (x, y) <- list, then group by x using groupWith ]
Prelude> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> process [(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")] [(1,["aa","cc","bb"]),(2,["aa"]),(3,["ff","gg"])]
3. Given a list of tuples like this:
dic =
[(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")]
Group hem by using second element of every tuple.
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts import Data.List import Data.Function (on) process :: [(Integer, String)] -> [(String, [Integer])] process list = [ (the y, x) | (x, y) <- list, then group by y using groupWith ]
*Main> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> process [(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")] [("aa",[1,2]),("bb",[1]),("cc",[1]),("ff",[3]),("gg",[3])] *Main>
Combine sorting and grouping
It is an
enhancement to the problem 2.
Given a list of
tuples like this:
dic =
[(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")]
You have to
group like below.
grp =
[(1,["aa","bb","cc"]), (2, ["aa"]), (3,
["ff","gg"])]
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts import Data.List import Data.Function (on) process :: [(Integer, String)] -> [(Integer, [String])] process list = [(the a, b) | let info = [ (x, y) | (x, y) <- list, then sortWith by y ], (a, b) <- info, then group by a using groupWith]
*Main> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> process [(1,"aa"),(1,"cc"),(2,"aa"),(3,"ff"),(3,"gg"),(1,"bb")] [(1,["aa","bb","cc"]),(2,["aa"]),(3,["ff","gg"])] *Main>
then group using f
With
this form of the group statement, f is required to simply have the type forall
a. [a] -> [[a]], which will be used to group up the comprehension so far
directly.
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts import Data.List process = [ x| x <- "hello", then group using subsequences]
*Main> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> process ["","h","e","he","l","hl","el","hel","l","hl","el","hel","ll","hll","ell","hell","o","ho","eo","heo","lo","hlo","elo","helo","lo","hlo","elo","helo","llo","hllo","ello","hello"]
ListUtil.hs
{-# LANGUAGE TransformListComp #-} import GHC.Exts import Data.List process xs ys = [ (x, y) | x <- xs, y <- ys, then group using subsequences ]
*Main> process "ab" "cd" [("",""),("a","c"),("a","d"),("aa","cd"),("b","c"),("ab","cc"),("ab","dc"),("aab","cdc"),("b","d"),("ab","cd"),("ab","dd"),("aab","cdd"),("bb","cd"),("abb","ccd"),("abb","dcd"),("aabb","cdcd")] *Main> *Main> :load ListUtil.hs [1 of 1] Compiling Main ( ListUtil.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> process "a" "cd" [("",""),("a","c"),("a","d"),("aa","cd")] *Main> *Main> process "ab" "c" [("",""),("a","c"),("b","c"),("ab","cc")] *Main> *Main> process "ab" "cd" [("",""),("a","c"),("a","d"),("aa","cd"),("b","c"),("ab","cc"),("ab","dc"),("aab","cdc"),("b","d"),("ab","cd"),("ab","dd"),("aab","cdd"),("bb","cd"),("abb","ccd"),("abb","dcd"),("aabb","cdcd")] *Main>
No comments:
Post a Comment