Как поставить ограничения на переменную типа вида "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)
.
Одиночное Наследование
фактически реализуя это для class
es только с одним наследованием требует кухонной раковины языковых расширений, в том числе 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
пакета, указанного в комментарии.