Haskell и условные структуры данных - PullRequest
3 голосов
/ 06 июля 2010

Можно ли написать что-то вроде:

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

А как именно это написать?

Ответы [ 4 ]

12 голосов
/ 06 июля 2010

Это похоже на ответ Даниэля Пратта, но более типичный подход состоит в том, чтобы исключить ограничения типов в определении данных, например:

data SomeData a = SomeValue
                | SomeConstructor a

Вместо этого вы должны наложить ограничение (Integral a) на все функции, которые в нем нуждаются, что вам придется делать, даже если вы добавили ограничение и в определение данных. Установив ограничение на определение данных, вы ничего не покупаете, но вынуждаете обойти ограничение на все случаи использования SomeData, даже те, которые не заботятся о том, что такое a. См. Глава 10 Реального мира Haskell для получения дополнительной информации.

6 голосов
/ 06 июля 2010

Например, используя GADT:

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

Пример использования:

*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
2 голосов
/ 06 июля 2010

Да, именно так, как вы хотите, но нужно упомянуть количественное определение:

{-# LANGUAGE ExistentialQuantification #-}

data SomeData = SomeValue
              | forall a . Integral a => SomeConstructor a
0 голосов
/ 06 июля 2010

Вы можете сделать что-то вроде этого:

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