Given this data type
data Val = X Int | Y Bool | Z Double deriving (Eq, Show)
and a list such as
let vals = [X 1, Z 2.7, Y True, X 2, Z 3.14, Y True]
how to group elements in vals
into this list,
[[X 1,X 2],[Y True,Y True],[Z 2.7, Z 3.14]]
You can combine multiple types with an and (for example, a name is a String and another String ), or you can combine types with an or (for example, a Bool is a True data constructor or a False data constructor). Types that are made by combining other types with an and are called product types.
In a data declaration, a type constructor is the thing on the left hand side of the equals sign. The data constructor(s) are the things on the right hand side of the equals sign. You use type constructors where a type is expected, and you use data constructors where a value is expected.
Maybe is a type constructor because it is used to construct new types (the result type depends on the type of a in Maybe a ), where such a type might be Maybe Int (notice, there's no type param a anymore, i.e. all type parameters are bound).
IO is a type constructor, not a value constructor. IO True would be a type, not a value (if True was a type).
To add to @RamonSnir's answer, the function for grouping a data type by constructors can be also constructed automatically using the "Scrap your boilerplate" framework:
{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data
import Data.Function (on)
import Data.List (groupBy, sort)
data Val = X Int | Y Bool | Z Double
deriving (Eq, Ord, Show, Typeable, Data)
vals :: [Val]
vals = [X 1, Z 2.7, Y True, X 2, Z 3.14, Y True]
main :: IO ()
main = print $ groupBy (on (==) toConstr) $ sort vals
The two important parts are:
Typeable
and Data
, andtoConstr
to get the representation of the constructor used in a particular value.I've the following:
data Val = X Int | Y Bool | Z Double deriving (Eq, Ord, Show)
vals :: [Val]
vals = [X 1, Z 2.7, Y True, X 2, Z 3.14, Y True]
valCtorEq :: Val -> Val -> Bool
valCtorEq (X _) (X _) = True
valCtorEq (Y _) (Y _) = True
valCtorEq (Z _) (Z _) = True
valCtorEq _ _ = False
And then:
*Main Data.List> groupBy valCtorEq $ sort vals
[[X 1,X 2],[Y True,Y True],[Z 2.7,Z 3.14]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With