Я пытаюсь создать простую встроенную DSL, которая должна позволять рекурсивным определениям. С этой целью я использую data-reify для преобразования AST выражения в граф.Как сохранить информацию о типе при преобразовании AST в Graph (eDSL)
В следующем примере код Signal
представляет собой AST, который может использовать пользователь (см. Сигнал test
). Это статически типизировано, поэтому не возможно добавить Signal Double
и Signal Int
, например.
{-# LANGUAGE GADTs, TypeFamilies #-}
import Control.Applicative hiding (Const)
import Data.Reify
data Value = VFloat64 Double
| VFloat32 Float
deriving (Show)
class HasValue a where
value :: a -> Value
instance HasValue Double where
value x = VFloat64 x
instance HasValue Float where
value x = VFloat32 x
data Signal t where
Add :: Num t => Signal t -> Signal t -> Signal t
Delay :: HasValue t => t -> Signal t -> Signal t
Const :: HasValue t => t -> Signal t
data Node s where
NodeAdd :: s -> s -> Node s
NodeDelay :: Value -> s -> Node s
NodeConst :: Value -> Node s
deriving (Show)
instance MuRef (Signal t) where
type DeRef (Signal t) = Node
mapDeRef f (Add a b) = NodeAdd <$> f a <*> f b
mapDeRef f (Const x) = pure $ NodeConst (value x)
mapDeRef f (Delay x a) = NodeDelay (value x) <$> f a
test :: Signal Double
test = Add (Const 1.0) test
Для оценки DSL, АСТ сначала преобразуется в Node
типа с использованием reifyGraph
из data-reify
. В текущей формулировке это включает использование HasValue
typeclass для преобразования значений каждого сигнала в тип суммы Value
. К сожалению, это делает диаграмму Node
эффективно динамически типизированной, потому что для оценки NodeAdd
я всегда буду должен проверить, используют ли два аргумента один и тот же конструктор.
Так что мой вопрос: Можно ли сохранить информацию о типе, который был все еще доступен в Signal
AST, при преобразовании в Node
графа?
Я уже пытался спараметрировать Node
с дополнительным типа (т.е. Node s a
), , но это не сработало, потому что DeRef (Signal t)
должна быть доброй * -> *
.
Вы можете включать в себя оценочную часть кода (по крайней мере типов)? Кроме того, вы пробовали 'Node a s' вместо' Node s a', разрешает ли это проблему с 'Deref (Signal t)' kind? – fizruk
Может быть, это помогает? http://hackage.haskell.org/package/data-treify –
Спасибо, этот пакет выглядит весьма интересным. К сожалению, документация немного разрежена ... – bzn