wen
wen

Reputation: 3848

Haskell and Conditional Data Structures

Is it possible to write something like:

data SomeData = SomeValue | (Integral a) => SomeConstructor a

And how exactly would one write this?

Upvotes: 4

Views: 698

Answers (4)

ony
ony

Reputation: 13223

Yep, exactly as you want, but need to mention quantification:

{-# LANGUAGE ExistentialQuantification #-}

data SomeData = SomeValue
              | forall a . Integral a => SomeConstructor a

Upvotes: 2

Paul Kuliniewicz
Paul Kuliniewicz

Reputation: 2731

This is similar to Daniel Pratt's answer, but the more typical approach is to leave off the type constraints on your data definition, like this:

data SomeData a = SomeValue
                | SomeConstructor a

Instead, you should put the (Integral a) constraint on any functions that require it, which you'd have to do even if you added the constraint to the data definition too. Putting the constraint on the data definition buys you nothing, but forces you to carry around the constraint on all uses of SomeData, even those that don't care what a is at all. See Chapter 10 of Real World Haskell for more.

Upvotes: 13

Daniel Pratt
Daniel Pratt

Reputation: 12077

You can do something like this:

data Integral a => SomeData a =
    SomeValue
    | SomeConstructor a

Upvotes: 0

Roman Cheplyaka
Roman Cheplyaka

Reputation: 38708

For example, using GADTs:

{-# LANGUAGE GADTs #-}
data SomeData
    where
    SomeValue :: SomeData
    SomeConstructor :: Integral a => a -> SomeData

Example of usage:

*Main> :t SomeValue 
SomeValue :: SomeData

*Main> :t SomeConstructor 15
SomeConstructor 15 :: SomeData

*Main> :t SomeConstructor "aaa"

<interactive>:1:0:
    No instance for (Integral [Char])
      arising from a use of `SomeConstructor' at <interactive>:1:0-20
    Possible fix: add an instance declaration for (Integral [Char])
    In the expression: SomeConstructor "aaa"

*Main> let x = SomeConstructor 15 in case x of { SomeConstructor p -> fromIntegral p :: Int }
15

Upvotes: 6

Related Questions