Je travaille avec Dominic Orchard. ensembles de niveaux de type qui suit son article de très près.
Je suis en train de construire un DSL pour exprimer la communication entre les parties au cours d'un programme concurrent synchrone. Une chose dont j'aurai besoin est la capacité d'exprimer des "sous-programmes" impliquant des sous-ensembles de la communauté originale ; ceci sera utilisé en conjonction avec fromUniversal
.
Voici une version allégée de mon code :
module Lib () where
import Data.Type.Nat (Nat)
import Data.Type.Set (IsSet, Subset)
import Polysemy (Sem, makeSem, reinterpret)
data Located (parties :: [Nat]) v = Located v
data Com (parties :: [Nat]) m a where
SendInt :: forall recipients senders parties m.
(Subset recipients parties,
Subset senders parties) =>
Located senders Int -> Com parties m (Located recipients Int)
FromUniversal :: forall parties m a.
Located parties a -> Com parties m a
-- Polysemy uses template haskell:
makeSem ''Com
--sendInt :: Member...=> (Located senders Int) -> Sem r (Located recipients Int)
--fromUniversal :: Member (Com parties) r => (Located parties a) -> Sem r a
--We can manually write them out instead of using makeSem;
--that helps make Located's type argument explicit.
-- Lift a program in a small community (clique) into a larger community's monad.
runClique :: forall parties clq s r a.
(IsSet parties,
IsSet clq,
Subset clq parties) =>
Sem (Com clq ': r) a -> Sem (Com parties ': r) (Located clq a)
runClique program = do
a <- (reinterpret _clique) program
return (Located a)
where _clique :: forall rInitial x.
Com clq (Sem rInitial) x -> Sem (Com parties ': r) x
_clique (SendInt l) = sendInt l
En _clique
il existe des contextes fournissant Subset recipients clq
y Subset csl parties
J'ai besoin que GHC comprenne d'une manière ou d'une autre que ceci implique Subset recipients parties
. Mais il n'y a pas de telle instance disponible.
Comment puis-je représenter la transitivité de "subset" pour les besoins des ensembles de niveau type ?
Voici le message d'erreur :
~/.../src/Lib.hs:35:31: error:
• Could not deduce (Subset recipients parties)
arising from a use of ‘sendInt’
from the context: (IsSet parties, IsSet clq, Subset clq parties)
bound by the type signature for:
runClique :: forall k (parties :: [Nat]) (clq :: [Nat]) (s :: k)
(r :: [(* -> *) -> * -> *]) a.
(IsSet parties, IsSet clq, Subset clq parties) =>
Sem (Com clq : r) a -> Sem (Com parties : r) (Located clq a)
at src/Lib.hs:(25,1)-(29,72)
or from: (x ~ Located recipients Int, Subset recipients clq,
Subset senders clq)
bound by a pattern with constructor:
SendInt :: forall k (recipients :: [Nat]) (senders :: [Nat])
(parties :: [Nat]) (m :: k).
(Subset recipients parties, Subset senders parties) =>
Located senders Int -> Com parties m (Located recipients Int),
in an equation for ‘_clique’
at src/Lib.hs:35:18-26
• In the expression: sendInt l
In an equation for ‘_clique’: _clique (SendInt l) = sendInt l
In an equation for ‘runClique’:
runClique program
= do a <- (reinterpret _clique) program
return (Located a)
where
_clique ::
forall rInitial x.
Com clq (Sem rInitial) x -> Sem (Com parties : r) x
_clique (SendInt l) = sendInt l
|
35 | _clique (SendInt l) = sendInt l
| ^^^^^^^^^
J'ai essayé d'ajouter simplement
instance {-# OVERLAPS #-} (Subset s t, Subset t v) => Subset s v where
subset xs = subset (subset xs :: Set t)
à Lib.hs (apparemment Subset
n'est pas un monde fermé ; je pensez à ) ; cela donne une variété de messages d'erreur différents selon les options du compilateur que j'utilise, ou si j'échange l'option OVERLAPS
para INCOHERENT
. L'essentiel semble être que GHC ne peut pas choisir une instance à utiliser, même si je promets qu'elle sera correcte.
J'ai essayé de faire le recipient
type explicite dans _clique
(afin que je puisse simplement ajouter les Subset recipients parties
au contexte), mais il semble que peu importe ce que je fais reinterpret
introduit/exige toujours une "nouvelle" x
et/ou recipients
Je n'ai pas trouvé de moyen de fournir le contexte pour la variable de type qui est réellement utilisée.
Il semble peu probable que cela soit impossible, mais je suis bloqué sur ce sujet depuis une journée et je suis dépassé par les événements.
0 votes
Je ne vois pas de code sur le post Reddit, pour ce que ça vaut. Pour moi, cela ressemble à un post complètement vide, juste le titre et aucun autre contenu.
1 votes
Quant à votre question : Je pense que vous devrez probablement définir
transitive :: (Subset s t, Subset t v) => Set s -> Set v
et l'appliquer manuellement aux moments opportuns. Cela fonctionne-t-il pour vous ? Si non, pouvez-vous modifier votre question pour expliquer pourquoi ? Une autre possibilité seraitclass Middleman t where proof :: (Subset s t, Subset t v) => Dict (Subset s v)
avec des instances pour la liste de niveau de type vide et pour la liste de niveau de type non vide, bien que je sois moins sûr que cela soit possible à mettre en œuvre.0 votes
@DanielWagner ; Il n'est pas clair comment
transitive
serait utile ; à aucun moment je n'essaie d'obtenir unSet v
d'unSet s
. Voulez-vous direSubset s t, Subset t v) => Set v -> Set s
(commeinstance (...) Subset s v
exigerait) ? La déclaration de l'instance n'a pas aidé (jusqu'à présent), et l'application de la fonction n'a pas de sens car il n'y a pas d'habitants de ce type d'instance.Set
types en vue.0 votes
En
Middleman
La tactique semble parler de la stratégie décrite. aquí mais je n'ai pas encore compris le sens de ce post, et je ne sais pas vraiment siDict
est une chose existante pour laquelle je devrais pouvoir trouver de la documentation. Avez-vous des liens ? Voulez-vous rédiger une réponse (pas nécessairement complète ou fonctionnelle) ?1 votes
Oui, bien sûr.
Set v -> Set s
Désolé. Je ne sais pas quoi vous dire. Vous allez devoir changer votre approche. J'aimerais beaucoup vous aider à le faire, mais pour l'instant, il est vraiment difficile de dire quoi que ce soit d'utile sans comprendre vos objectifs. Si vous nous emmenez sur le chemin du jardin -- quel est le niveau supérieur ce que vous essayez d'atteindre, et quelles sont toutes les étapes qui, selon vous, mènent inévitablement à ce besoin ? -- Nous pourrons alors vous indiquer les endroits où vous pourriez vous écarter du chemin. Dict est aquí .0 votes
J'ai ajouté beaucoup plus de contexte et de code, et supprimé le lien reddit.
1 votes
Au lieu d'avoir
SendInt :: (Subset recipients parties, Subset senders parties) => ..
vous pourriez plutôt utiliserSendInt :: SubsetWitness recipients parties -> SubsetWitness senders parties -> ...
oùSubsetWitness
est un type qui témoigne de la preuve qu'un ensemble est un sous-ensemble d'un autre. Ensuite, définissez également votre propre classeclass Subset s t where subsetWitness :: SubsetWitness s t
; vous récupérez la syntaxe dans l'OP avecsendInt' = sendInt subsetWitness subsetWitness
.0 votes
@user2407038 ; Cela semble plausible, mais votre description ne me permet pas de comprendre comment obtenir la transitivité.