Возможно ли сделать гетерогенный Data.Map
в Haskell с GADT
вместо Dynamic
? Я попытался смоделировать гетерогенную коллекцию, как изложено в this answer:Гетерогенные данные. Карта в Haskell
{-# LANGUAGE GADTs #-}
class Contract a where
toString :: a -> String
data Encapsulated where
Encapsulate :: Contract a => a -> Encapsulated
getTypedObject :: Encapsulated -> a
getTypedObject (Encapsulate x) = x
Идея заключается в том, что Encapsulated
может быть использован для хранения различных предметов из TypeClass a
, а затем экстрагируют во время выполнения для конкретного типа.
Я получаю ошибку о типе x
не соответствует Contract a
. Возможно, мне нужно указать какие-то ограничения класса, чтобы сообщить GHC
, что тип x
в Encapsulate x
такой же, как a
в Contract a
?
T.hs:10:34:
Couldn't match expected type ‘a’ with actual type ‘a1’
‘a1’ is a rigid type variable bound by
a pattern with constructor
Encapsulate :: forall a. Contract a => a -> Encapsulated,
in an equation for ‘getTypedObject’
at T.hs:10:17
‘a’ is a rigid type variable bound by
the type signature for getTypedObject :: Encapsulated -> a
at T.hs:9:19
Relevant bindings include
x :: a1 (bound at T.hs:10:29)
getTypedObject :: Encapsulated -> a (bound at T.hs:10:1)
In the expression: x
In an equation for ‘getTypedObject’:
getTypedObject (Encapsulate x) = x
Я пытаюсь этот подход, потому что у меня есть объекты JSON различных типов, и в зависимости от типа, который декодируется во время выполнения через проволоку, мы хотим получить соответствующий тип конкретного builder
из Map
(нагруженного во время выполнения IO в main
из файлов конфигурации и передается функции) и передавать его декодированные данные JSON того же типа.
Dynamic
библиотека будет работать здесь. Тем не менее, мне интересно узнать, есть ли другие возможные подходы, такие как GADTs
или datafamilies
.
Возможно, стоит отметить, что в этом случае вам даже не нужны GADT; достаточно включить 'ExistentialQuantification', чтобы написать что-то вроде' data Encapsulated = forall a. Показать a => Инкапсулировать a' –
Для многих (наиболее?) Целей и, почти наверняка, этого, 'Dynamic' является концептуальным излишеством и достаточно ограничение' Typeable'. 'data Box, где Box :: Typeable a => a -> Box'. Затем вы можете использовать функции из 'Data.Typeable', чтобы' Maybe' получить значение из поля. – dfeuer
В GHC 8.2, 'Typeable', как ожидается, станет значительно более мощным, более чем обладая функциональностью, предлагаемой в настоящее время' Dynamic'. – dfeuer