Я пытаюсь немного повеселиться с навязчивым программированием в Haskell, более конкретно с типом безопасного поиска. Previously, я спросил о том, как осуществить операцию подстановки для следующих типов данных:Подробнее о типе безопасного поиска для гетерогенных списков в Haskell
data Attr (xs :: [(Symbol,*)]) where
Nil :: Attr '[]
(:*) :: (Sing s, t) -> Attr xs -> Attr ('(s , t) ': xs)
И я получил ответ:
lookupAttr :: (Lookup s env ~ 'Just t) => Sing s -> Attr env -> t
lookupAttr s ((s', t) :* env') = case s %:== s' of
STrue -> t
SFalse -> lookupAttr s env'
Это работает отлично. Теперь я хочу, чтобы определить гетерогенный список значений типизированного синтаксиса, представленный типом Exp
:
{-# LANGUAGE GADTs, TypeFamilies, DataKinds, TypeOperators, PolyKinds #-}
import Data.Singletons.Prelude.List
import Data.Singletons.Prelude.Bool
import Data.Singletons.Prelude.Eq
data Exp (env :: [(Symbol,*)]) :: * -> * where
Value :: String -> Exp env String
Var :: (Lookup s env ~ 'Just t) => Sing s -> Exp env t
Op :: Exp env t -> Exp env t -> Exp env t
гетерогенный тип списка определяется по типу Env
данных:
data Env (env :: [(Symbol,*)]) where
Nil :: Env '[]
Cons :: (Lookup s' env ~ 'Nothing) =>
(Sing s' ,
Exp ('(s', a) ': env) a) ->
Env env ->
Env ('(s',a) ': env)
Используя эти типы данных, Я определяю функцию просмотра с помощью какого-то экзистенциальной квантификации (типа Ex2
):
data Ex2 (p :: k -> k' -> *) where
Ex2 :: p e i -> Ex2 p
lookupEnv :: Lookup s env ~ 'Just t => Sing s -> Env env -> Ex2 Exp
lookupEnv s (Cons (s',e) env)
= case s %:== s' of
STrue -> Ex2 e
SFalse -> lookupEnv s env
до сих пор , так хорошо. Теперь я прихожу к некоторым интересным проблемам:
1) Есть ли способ определить lookupEnv
без использования этого вида экзистенциальной количественной оценки, предоставляемой по типу Ex2
?
2) Предположим, что я хочу определить операцию для изменения позиции ввода в значение типа Env
. Очевидная попытка определить эту функцию является
modifyEnv :: Lookup s env ~ 'Just t => Sing s -> Exp env t -> Env env -> Env env
modifyEnv s e (Cons (s',e') env')
= case s %:== s' of
STrue -> Cons (s', Op e e') env'
SFalse -> Cons (s',e') (modifyEnv s e env')
Функция modifyEnv
составить некоторое выражение с другим в окружающей среде. Эта функция не принимается GHC, которая возвращает загадочное сообщение об ошибке. Как я могу определить такую функцию модификации?
Hi @Cactus! Спасибо за Ваш ответ! Я уже рассмотрел использование типизированных индексов DeBruijn, но они немного сложны для создания вручную для пользователей EDSL (моя конечная цель - создать EDSL). Из-за этого я пытаюсь использовать индексированные среды Symbol. –