Как поставить ограничения на переменную типа вида "Constraint"?
я играю с
2 ответов
самое близкое, что мы можем получить, это Class1 класс, reifys отношения между классом и одно ограничение суперкласса, как класс. Он основан на Class С ограничения.
во-первых, мы возьмем короткий тур пакета ограничений. А Dict захватывает словарь для Constraint
data Dict :: Constraint -> * where
Dict :: a => Dict a
:- захватывает, что одно ограничение влечет за собой другой. Если у нас есть a :- b, всякий раз, когда у нас есть ограничение a мы можем создать словарь для ограничения b.
newtype a :- b = Sub (a => Dict b)
нам нужно доказательство, подобное :-, мы должны знать, что forall a. h a :- b a или h a => Dict (b a).
Одиночное Наследование
фактически реализуя это для classes только с одним наследованием требует кухонной раковины языковых расширений, в том числе OverlappingInstances.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}
import Data.Constraint
определим класс ограничений добрый k -> Constraint где ограничение имеет один суперкласс.
class Class1 b h | h -> b where
cls1 :: h a :- b a
теперь мы оснащены для решения нашей проблемы примера. У нас есть класс A требует Show экземпляра.
class Show a => A a
instance A Int
Show - это суперкласс A
instance Class1 Show A where
cls1 = Sub Dict
мы хотим написать Show экземпляров Some
data Some (c :: * -> Constraint) where
Some :: c a => a -> Some c
у нас можете Show a Some Show.
instance Show (Some Show) where
showsPrec x (Some a) = showsPrec x a
у нас можете Show a Some h, когда h есть один суперкласс!--17--> и мы могли бы показать Some b.
instance (Show (Some b), Class1 b h) => Show (Some h) where
showsPrec x (Some (a :: a)) =
case cls1 :: h a :- b a of
Sub Dict -> showsPrec x ((Some a) :: Some b)
это позволяет нам писать
x :: Some A
x = Some (1 :: Int)
main = print x
вы не можете сделать Some c экземпляр Show, кроме тривиально.
вы хотите show на a внутри Some, но эта переменная экзистенциально количественная, поэтому мы не можем зависеть от каких-либо знаний типа a. В частности, мы не можем знать, что a пример Show.
EDIT: я расширю свой ответ.
Даже с большим количеством машин и отказавшись от Show например, я все еще не думаю то, что вы хотите, возможно из-за экзистенциальной квантификации.
сначала я перепишу Some в более знакомой форме
data Dict p where
Dict :: p a => a -> Dict p
обычный способ говорить о" ограничениях, подразумевающих ограничения", - это концепция ограничения.
data p :- q where
Sub :: p a => Dict q -> p :- q
мы можем думать о значение типа p :- q как доказательство того, что если ограничение forall a. p a, то forall a. q a следующий.
теперь попробуем написать толковое show-ишь функция
showD :: p :- Show -> Dict p -> String
showD (Sub (Dict a)) (Dict b) = show b
на первый взгляд, это может сработать. Мы ввели в область действия следующие ограничения (простите псевдо -exists синтаксис)
(0) p :: * -> Constraint
(1) exists a. p a -- (Dict p)
(2) exists b. p b => Show b -- (p :- Show)
но теперь все разваливается, GHC справедливо жалуется:
main.hs:10:33:
Could not deduce (Show a2) arising from a use of `show'
from the context (p a)
bound by a pattern with constructor
Sub :: forall (p :: * -> Constraint) (q :: * -> Constraint) a.
(p a) =>
Dict q -> p :- q,
in an equation for `showD'
at main.hs:10:8-19
or from (Show a1)
bound by a pattern with constructor
Dict :: forall (p :: * -> Constraint) a. (p a) => a -> Dict p,
in an equation for `showD'
at main.hs:10:13-18
or from (p a2)
bound by a pattern with constructor
Dict :: forall (p :: * -> Constraint) a. (p a) => a -> Dict p,
in an equation for `showD'
at main.hs:10:23-28
потому что невозможно унифицировать a С (1) С b С (2).
это та же самая существенная идея, которая используется во всем constraints пакета, указанного в комментарии.