Ответ 1
В Scala ваша ADT делает A
, B
, C
подтипами Foo
. В Haskell у нас нет подтипов, поэтому A
, B
, C
являются конструкторами типа Foo
.
Несколько возможных обходных путей:
-
Повторите поля. Это самый основной вариант.
data Foo = A Int | B String | C Int String
-
Определите дополнительные типы, чтобы мы могли использовать их более одного раза.
data AT = AT Int -- can have many arguments data BT = BT String -- can have many arguments data Foo = A AT | B BT | C AT BT
-
Эксплуатировать ГАДТ
data FooTag = AT | BT | CT data Foo (tag :: FooTag) where A :: Int -> Foo 'AT B :: String -> Foo 'BT C :: Foo 'AT -> Foo 'BT -> Foo 'CT
Здесь, в последней строке мы можем ссылаться на "значения, построенные с использованием
A
", используя типFoo 'AT
, поскольку тегAT
используется только конструкторомA
Обратите внимание, что этот подход добавляет параметр тега вFoo
, поэтому он немного меняет интерфейс: мы больше не можем писатьbar :: Foo ->...
, но мы должны написатьbar :: Foo t ->...
(или использовать экзистенциальные типы).