Ich spiele mit Frei wie Ideen um und fand diese:Gibt es eine Verallgemeinerung dieser Free-ähnlichen Konstruktionen?
{-# LANGUAGE RankNTypes #-}
data Monoid m = Monoid { mempty :: m, mappend :: m -> m -> m }
data Generator a m = Generator { monoid :: Monoid m, singleton :: a -> m }
newtype Free f = Free { getFree :: forall s. f s -> s }
mkMonoid :: (forall s. f s -> Monoid s) -> Monoid (Free f)
mkMonoid f = Monoid {
mempty = Free (mempty . f),
mappend = \a b -> Free $ \s -> mappend (f s) (getFree a s) (getFree b s)
}
freeMonoid :: Monoid (Free Monoid)
freeMonoid = mkMonoid id
mkGenerator :: (forall s. f s -> Generator a s) -> Generator a (Free f)
mkGenerator f = Generator {
monoid = mkMonoid (monoid . f),
singleton = \x -> Free $ \s -> singleton (f s) x
}
freeGenerator :: Generator a (Free (Generator a))
freeGenerator = mkGenerator id
Ich mag die Bedingungen finden, unter denen ich einen funcion schreiben konnte:
mkFree :: (??? f) => f (Free f)
aber ich habe nicht in der Lage gewesen, um eine sinnvolle Struktur für f
zu finden (eine andere als die triviale, in der mkFree
eine Methode von ???
ist), die es ermöglichen würde, diese Funktion zu schreiben. Insbesondere würde mein ästhetischer Sinn bevorzugen, wenn diese Struktur den Free
Typ nicht erwähnt.
Hat jemand so etwas schon mal gesehen? Ist diese Verallgemeinerung möglich? Gibt es eine bekannte Verallgemeinerung in eine Richtung, an die ich noch nicht gedacht habe?
Ich habe diese auf Hackage (die church encoded version genau zu sein.): Http://hackage.haskell.org/ Paket/Frei-Funktoren-0.1.1, aber ich glaube nicht, dass du das willst? –
Richtig, nachdem ich das, was du hast, zu meinem Paket gefunden habe, glaube ich zu verstehen, was du willst. Übersetzt würde es sein, wie man automatisch eine Instanz "Monoid (Free Monoid a)" oder generell eine Instanz "c (Free c a)" erzeugt. F. e. die 'Num'-Instanz hier: https://github.com/sjoerdvisscher/free-functors/blob/master/examples/FreeNum.hs. Es ist im Grunde 'liftAn' plus ein wenig Rauschen für die einfachen Fälle, die mit einigen Template Haskell lösbar sein sollte. Aber ich denke, der komplett generische Fall ist ziemlich kompliziert. –
@SjoerdVisscher, es ist das Rauschen, das mich interessiert (deshalb verwende ich hier Datentypen und keine Klassen). Es fühlt sich an wie "Traversable", aber es funktioniert auch bei negativen Vorkommen des Parameters. Ich habe mich gefragt, ob es eine algebraische Eigenschaft (wie 'Traversable') gibt, und nicht strukturelle (introspektive Typ-Signaturen), aus denen diese Instanz erzeugt werden könnte. – luqui