Я не знаю точного контекста, в котором вам требуются эти SymVal (Vec a n)
экземпляры, но, вообще говоря, если у вас есть фрагмент кода, требующий экземпляр SymVal (Vec a n)
, вы должны добавить его как контекст:
foo :: forall (a :: Type) (n :: Nat). SymVal (Vec a n) => ...
Когда foo
вызывается с конкретным n
, решатель ограничений сокращает приложение семейства типов и использует экземпляры
instance ( SymVal p, SymVal q ) => SymVal (p,q)
В конце этого процесса решателю ограничений потребуется экземпляр для SymVal a
. Таким образом, вы сможете позвонить foo
:
- если вы укажете заданное значение для
n
, что позволит полностью сократить приложения семейства типов, и использовать тип a
, у которого есть экземпляр для SymVal
:
bar :: forall (a :: Type). SymVal a => ...
bar = ... foo @a @(S (S (S Z))) ...
baz :: ...
baz = ... foo @Float @(S Z) ... -- Float has a SymVal instance
- отложить поиск экземпляра, указав тот же контекст:
quux :: forall (a :: Type) (n :: Nat). SymVal (Vec a n) => ...
quux = ... foo @a @n ...
GHC не может автоматически вывести SymVal (Vec a n)
из SymVal a
, потому что без дополнительного контекста он не может уменьшить приложение семейства типов и, следовательно, не знает, какой экземпляр выбрать. Если вы хотите, чтобы GHC мог выполнить этот вывод, вам нужно будет явно передать n
в качестве аргумента. Это можно эмулировать с помощью синглтонов:
deduceSymVal :: forall (a :: Type) (n :: Nat). Sing n -> Dict (SymVal a) -> Dict (SymVal (Vec a n))
deduceSymVal sz@SZ Dict =
case sz of
( _ :: Sing Z )
-> Dict
deduceSymVal ( ss@(SS sm) ) Dict
= case ss of
( _ :: Sing (S m) ) ->
case deduceSymVal @a @m sm Dict of
Dict -> Dict
(Обратите внимание, что эти неприятные операторы case были бы устранены с помощью приложений типов в шаблонах, mais c'est la vie.)
Затем вы можете использовать эту функцию, чтобы позволить GHC вывести ограничение SymVal (Vec a n)
из ограничения SymVal a
, если вы можете предоставить синглтон для n
(что равносильно явной передаче n
, а не параметризации над ним):
flob :: forall (a :: Type) (n :: Nat). (SymVal a, SingI n) => ...
flob = case deduceSymVal @a (sing @n) Dict of
Dict -- matching on 'Dict' provides a `SymVal (Vec a n)` instance
-> ... foo @a @n ...
person
Sam Derbyshire
schedule
04.07.2019
instance SymVal a => SymVal (Vec a Z)
иinstance SymVal (Vec a n) => SymVal (Vec a (S n))
? - person bradrn   schedule 04.07.2019