Я хочу создать структуру данных для хранения элементов, помеченных на уровне типа, с помощью Symbol. Этот:
data Store e (ss :: [Symbol]) where
Nil :: Store e '[]
Cons :: e s -> Store e ss -> Store e (s ': ss)
data HasElem (a :: k) (as :: [k]) where
AtHead :: HasElem a (a ': as)
InTail :: HasElem a as -> HasElem a (b ': as)
class HasElemC (a :: k) (as :: [k]) where hasElem :: HasElem a as
instance HasElemC {OVERLAPPING} a (a ': as) where hasElem = AtHead
instance HasElemC a as => HasElemC a (b ': as) where hasElem = InTail hasElem
from :: HasElemC s ss => Store e ss -> e s
from = from' hasElem
from' :: HasElem s ss -> Store e ss -> e s
-- from' _ Nil = undefined
from' h (Cons element store) = case h of
AtHead -> element
InTail h' -> from' h' store
вроде работает, если не обращать внимания на тот факт, что компилятор предупреждает меня о том, что я не предоставил определение from' _ Nil
(кстати, почему это так? есть ли способ остановить это?) Но что я действительно хотел сделать в начале, так это использовать синглтоны библиотеку в идиоматической манере вместо того, чтобы писать собственный код на уровне типов. Что-то вроде этого:
import Data.Singletons.Prelude.List
data Store e (ss :: [Symbol]) where
Nil :: Store e '[]
Cons :: Sing s -> e s -> Store e ss -> Store e (s ': ss)
from :: Elem s ss ~ True => Store e ss -> e s
from (Cons evidence element nested) = ???
К сожалению, я не мог понять, как преобразовать контекст в пропозициональное равенство. Как вы можете использовать строительные блоки из библиотеки singletons, чтобы делать то, что я пытаюсь сделать?
[email protected], синглтоны@2.1
from'
, добавив функцииstoreHead :: Store e (s ': ss) -> e s
иstoreTail :: Store e (s ': ss) -> Store e ss
и использовать их в магазине после того, как вы сопоставитеAtHead
илиInTail
. - person cchalmers   schedule 10.07.2016HasElemC
пересекаются. GHC сочтет невозможным снять ограничениеHasElemC
, потому что он не проверяет предварительные условия при поиске доказательства. К счастью, есть известный прием с использованием семейств типов иUndecidableInstances
. (На самом деле это одно из немногих удачных применений семейств логических типов.) - person Benjamin Hodgson♦   schedule 10.07.2016HasElemC
бесполезен из-за того, как вы определили свои экземпляры. Попробуйте написатьx = HasElem "a" '["a"]; x = hasElem
. Он не будет проверять тип. - person Benjamin Hodgson♦   schedule 11.07.2016from
, выполняет проверку типов и работает правильно. Вам просто нужно отметить экземпляр AtHead OVERLAPPING/InTail экземпляр OVERLAPPABLE. Вы говорите, что не должно? - person NioBium   schedule 11.07.2016a /~ (q ': a)
, потому что семейства типов могут представлять бесконечное количество типов. Перекрывающиеся экземпляры с радостью это сделают, потому что это не влияет на безопасность типов. - person dfeuer   schedule 11.07.2016