Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping data types by constructor in Haskell

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]]
like image 231
elm Avatar asked Oct 22 '14 05:10

elm


People also ask

How data types are combined in Haskell?

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.

What are type constructors in Haskell?

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.

Is maybe a data constructor in Haskell?

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).

Is Io a data constructor in Haskell?

IO is a type constructor, not a value constructor. IO True would be a type, not a value (if True was a type).


2 Answers

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:

  • derive Typeable and Data, and
  • use toConstr to get the representation of the constructor used in a particular value.
like image 190
Petr Avatar answered Oct 16 '22 20:10

Petr


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]]
like image 43
Ramon Snir Avatar answered Oct 16 '22 19:10

Ramon Snir