Я пытаюсь использовать некоторые расширения Haskell для реализации простой DSL. Функция, которая мне нужна, это иметь контекст уровня типа для переменных. Я знаю, что это обычное место в таких языках, как Агда или Идрис. Но я хотел бы знать, можно ли добиться тех же результатов в Haskell.Тип уровня среды в Haskell
Моя идея: использовать списки ассоциаций типов. Код выглядит следующим образом:
{-# LANGUAGE GADTs,
DataKinds,
PolyKinds,
TypeOperators,
TypeFamilies,
ScopedTypeVariables,
ConstraintKinds,
UndecidableInstances #-}
import Data.Proxy
import Data.Singletons.Prelude
import Data.Singletons.Prelude.List
import GHC.Exts
import GHC.TypeLits
type family In (s :: Symbol)(a :: *)(env :: [(Symbol, *)]) :: Constraint where
In x t '[] =()
In x t ('(y,t) ': env) = (x ~ y , In x t env)
data Exp (env :: [(Symbol, *)]) (a :: *) where
Pure :: a -> Exp env a
Map :: (a -> b) -> Exp env a -> Exp env b
App :: Exp env (a -> b) -> Exp env a -> Exp env b
Set :: (KnownSymbol s, In s t env) => proxy s -> t -> Exp env()
Get :: (KnownSymbol s, In s t env) => proxy s -> Exp env t
test :: Exp '[ '("a", Bool), '("b", Char) ] Char
test = Get (Proxy :: Proxy "b")
семейного типа In
моделей типа списка уровень членства ограничений, который используется для того, чтобы переменная может быть использована только тогда, когда он находится на данной среде env
.
Проблема заключается в том, что GHC решатель не может повлечь за собой ограничение In "b" Char [("a",Bool), ("b",Char)]
для test
функции, что дает следующее сообщение об ошибке:
Could not deduce (In "b" Char '['("a", Bool), '("b", Char)])
arising from a use of ‘Get’
In the expression: Get (Proxy :: Proxy "b")
In an equation for ‘test’: test = Get (Proxy :: Proxy "b")
Failed, modules loaded: Main.
Я использую GHC 7.10.3. Любой отзыв о том, как я могу решить это или объяснить, почему это невозможно, очень приветствуется.
Ты собираешься рассердиться программистами Форта! – dfeuer