È possibile con questa libreria: https://github.com/mikeizbicki/ifcxt.Essere in grado di chiamare show
su un valore che può o non può avere un'istanza Show
è uno dei primi esempi che fornisce. Questo è come si potrebbe adattare che per V a
:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
import IfCxt
import Data.Typeable
mkIfCxtInstances ''Show
data V a = V a
instance forall a. IfCxt (Show a) => Show (V a) where
show (V a) = ifCxt (Proxy::Proxy (Show a))
(show a)
"<<unshowable>>"
Questa è l'essenza di questa libreria:
class IfCxt cxt where
ifCxt :: proxy cxt -> (cxt => a) -> a -> a
instance {-# OVERLAPPABLE #-} IfCxt cxt where ifCxt _ t f = f
io non lo comprendiamo pienamente, ma questo è come penso che funziona:
Essa non viola l'ipotesi "mondo aperto" più di quanto
instance {-# OVERLAPPABLE #-} Show a where
show _ = "<<unshowable>>"
fa. L'approccio è in realtà molto simile a questo: aggiungere un caso predefinito a cui ricorrere per tutti i tipi che non hanno un'istanza in ambito. Tuttavia, aggiunge qualche riferimento indiretto per non creare confusione con le istanze esistenti (e per consentire a diverse funzioni di specificare valori predefiniti diversi). IfCxt
opere come aa "meta-class", una classe su vincoli, che indica se esistano questi casi, con un caso di default che indica "false.":
instance {-# OVERLAPPABLE #-} IfCxt cxt where ifCxt _ t f = f
utilizza TemplateHaskell per generare un lungo elenco di istanze per quella classe:
instance {-# OVERLAPS #-} IfCxt (Show Int) where ifCxt _ t f = t
instance {-# OVERLAPS #-} IfCxt (Show Char) where ifCxt _ t f = t
che implica anche che tutte le istanze che non erano di portata, quando è stato chiamato mkIfCxtInstances
sarà considerato inesistente.
L'argomento proxy cxt
viene utilizzato per passare un Constraint
alla funzione, l'argomento (cxt => a)
(non avevo idea RankNTypes consentito che) è un argomento che può uso il vincolo cxt
, ma finché tale argomento è inutilizzato, il vincolo non ha bisogno di essere risolto. Questo è simile a:
f :: (Show (a -> a) => a) -> a -> a
f _ x = x
L'argomento proxy
fornisce il vincolo, quindi il vincolo IfCxt
è risolto sia alla tesi t
o f
, se è t
allora c'è qualche IfCxt
caso in cui questo vincolo viene fornito il che significa che può essere risolto direttamente, se è f
quindi il vincolo non viene mai richiesto, quindi viene eliminato.
Questa soluzione è imperfetta (come nuovi moduli possono definire nuovi Show
casi che non funzioneranno a meno che non chiede anche mkIfCxtInstances
), ma essere in grado di farlo avrebbe violare il presupposto mondo aperto.
Haskell è un linguaggio completamente cancellato dal testo; in fase di esecuzione, le strutture allocate alla memoria non contengono tag che possono essere utilizzati per recuperare i loro tipi o le classi implementate da questi tipi. Pertanto, non esiste un operatore 'instanceof' come Java o lingue simili. (Esistono tecniche più avanzate che possono essere utilizzate in alcuni casi per la riflessione del tipo di runtime simile, ma se sei un principiante devi prima attenersi alle nozioni di base!) –
Questo comportamento non può essere implementato, perché filosoficamente, il tipo _every è in ogni classe_.Certo, se il compilatore non può _find_ un'istanza 'Show' per qualche tipo si prova a' show', ci sarà un errore; ma questo è inteso come concettualmente "hai dimenticato di scrivere l'istanza necessaria" invece di "hai provato a mostrare un tipo che non è _ visibile". Le classi di tipi sono aperte, in seguito chiunque può definire le istanze per alcune classi di libreria. Il compilatore non può provare che ciò non accadrà, quando compila la libreria! – leftaroundabout
Detto questo: il comportamento può essere emulato con [istanze sovrapposte] (https://downloads.haskell.org/~ghc/7.8.1/docs/html/users_guide/type-class-extensions.html#instance-overlap) , che sono considerati un trucco un po 'brutto (o addirittura pericoloso). Forse meglio abbinare l'idea sono [famiglie di tipo chiuso] (http://research.microsoft.com/en-us/um/people/simonpj/papers/ext-f/axioms-extended.pdf), anche se non lo fanno prontamente ti permettono di implementare quella mostra. – leftaroundabout