0

I have two datatypes, A and B, which I have defined as:

data A = A { aFoo :: Int, aBar :: String }
data B = B { bFoo :: Int, bBar :: String, bBaz :: Float }

I now need to create a heterogeneous list of As and Bs, so I define a sum type, C, as:

data C = CA A | CB B

I would now like to define the functions

cFoo :: C -> Int
cBar :: C -> String

This can be achieved with pattern matching...

cFoo (CA a) = aFoo a
cFoo (CB b) = bFoo b

cBar (CA a) = aBar a
cBar (CB b) = bBar b

...but this becomes tedious with data types of many fields. I was wondering if there is a simple solution using template Haskell, or if it wouldn't be worth the effort. I have intermediate knowledge of Haskell, but am relatively new to Template Haskell. Any help is appreciated.

jub0bs
  • 60,866
  • 25
  • 183
  • 186
Kwarrtz
  • 2,693
  • 15
  • 24
  • It's unclear what you're trying to achieve with this pattern here; Why not just have `data FooBar = FooBar { foo :: Int, bar :: String }` and `aToFooBar :: A -> FooBar` and `bToFooBar :: B -> FooBar` and `data C = C FooBar`? If it's all the same to you anyway? – Cubic Aug 17 '15 at 02:24
  • I'd ultimately like to make `cFoo` and `cBar` lenses. – Kwarrtz Aug 17 '15 at 04:09

1 Answers1

1
{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data A = 
  A 
    { _aFoo :: Int
    , _aBar :: String 
    }

data B = 
  B 
    { _bFoo :: Int
    , _bBar :: String
    , _bBaz :: Float 
    }

makeLenses ''A
makeLenses ''B

data C 
  = CA A 
  | CB B

makePrisms ''C

That will give you seven functions: aFoo, aBar, bFoo, bBar, bBaz, _CA and _CB.

I suggest you read this tutorial: lens over tea #6: Template Haskell.

MCH
  • 2,124
  • 1
  • 19
  • 34