Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A general way of comparing constructors of two terms in Haskell [duplicate]

Tags:

haskell

Given two terms t1 t2 of some data type, is there some way to check if t1 and t2 start with the same constructor, without doing some exhaustive case or pattern matching over constructors? Like if my type is Either a b, then I want

checkConst (Left x) (Left y) = True
checkConst (Right x) (Left y) = False
...

and so on without actually doing that pattern matching, and in a way that is generalizable to other types with on the order of 10 constructors. Is there a nice way to do this?

like image 352
Daniel Satanove Avatar asked Jan 04 '23 01:01

Daniel Satanove


2 Answers

You are probably looking for the generics functionality available in the Data.Data module. If you define a data type with a derived Data instance, like so:

{-# LANGUAGE DeriveDataTypeable #-}
import Data.Data
data Foo = Bar1 Int
         | Bar2 String String
         | Bar3 Double
         deriving (Data)

then you can retrieve the constructor for a value with toConstr:

> toConstr (Bar1 1)
Bar1
> toConstr (Bar2 "hello" "there")
Bar2
>

These are values of type Constr that can be compared for equality, so you can define:

checkConst :: (Data g) => g -> g -> Bool
checkConst x y = toConstr x == toConstr y

and get:

> checkConst (Bar1 10) (Bar1 20)
True
> checkConst (Bar1 10) (Bar3 20)
False
>
like image 180
K. A. Buhr Avatar answered Jan 05 '23 15:01

K. A. Buhr


You could use some kind of intermediate type which can uniquely distinguish each constructor and has an Eq instance. For example, you could use an Int to distinguish each data constructor, and then compare the values.

checkConst x y = toInt x == toInt y
  where
    toInt (Left _)  = 1 :: Int
    toInt (Right _) = 2

If your type implements Data from Data.Data, you could use toConstr to use Constr as your intermediate type. In the case of Either this isn't necessary because you could use isRight x == isRight y, but for a data type with 10 constructors, this would be cleaner.

like image 23
4castle Avatar answered Jan 05 '23 15:01

4castle