Sto lavorando a un functor applicativo che contiene un monoide per "visualizzare" l'esecuzione. Tuttavia, a volte non mi interessa affatto questa parte, quindi la scelta di monoid è irrilevante in quanto non verrà mai consumata. Ho semplificato ciò che ho in:Utilizzo di tipi di vincoli e famiglie di tipi con vincoli "limitati"
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a() where render = const()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render
viene utilizzato per trasformare i vari a
s in un unico b
. Merge
è una grande semplificazione del mio attuale functor, ma il punto è che contiene un tipo family/constraint e la mia intenzione è quella di specificare esattamente cosa richiede Render
a Merge
.
Ora, potrei voler "correre" il Merge
, ma eliminare la vista, che è simile a qualcosa di simile:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of() -> 5
Ma questo non riuscirà perché:
Impossibile dedurre
(Renderer a())
derivanti da un utilizzo dimerge
ho scelto come mio ()
monoid perché f orall a
, abbiamo un'istanza di Render a()
. Quindi, se c'era un modo per dire che Merge a
significa solo una raccolta Render
vincoli allora funzionerebbe bene. Naturalmente, Merge a
è più generale di quello - potrebbe aggiungere vincoli arbitrari, il che spiega l'errore di compilazione.
È comunque necessario ottenere ciò che voglio senza cambiando la firma di runFoo
?
Vuol 'renderer' includono sempre esattamente un' Render'? –
@Tinctorius - no, generalmente dipende dalla quantità di tipi distinti nei campi di 'Foo' – ocharles
C'è un motivo per cui" Merge' non ha anche 'b' come parametro? –