Oltre a @ di DanielWagner risposta, in alternativa è quella di utilizzare Scrap your boilerplate (AKA "SYB"). Ti permette di trovare il primo sottotipo di un determinato tipo. Così si potrebbe definire
{-# LANGUAGE DeriveDataTypeable #-}
import Control.Monad
import Data.Data
import Data.Generics.Schemes
import Data.Typeable
data Foo = X (String, Int) | A String | B String | C String | D String
deriving (Show, Eq, Ord, Data, Typeable)
fooString :: Foo -> Maybe String
fooString = msum . gmapQ cast
e fooString
tornerà il primo String
argomento dei tuoi costruttori. Funzione cast
filtri fuori String
se gmapQ
ottiene i valori filtrati per tutti i sottotemi immediati.
Tuttavia, questo non restituirà il String
da X
, perché X
non ha immediata String
sottotermine, si ha un solo sottotermine di tipo (String, Int)
. Al fine di ottenere il primo String
ovunque nella gerarchia termine, è possibile utilizzare everywhere
:
fooString' :: Foo -> Maybe String
fooString' = everything mplus cast
Si noti che questo approccio è un po 'fragile: Comprende semplicemente tutto String
s che trova, che potrebbe non essere sempre quello che si vuole , in particolare, se in seguito si estende il tipo di dati (o alcuni tipi di dati a cui fa riferimento).
fonte
2015-08-22 18:39:22
Anche se non è disponibile nella lingua questo tipo di funzionalità (eccetto, si potrebbe considerare l'utilizzo di [generics] (https://wiki.haskell.org/Generics) o [Template Haskell] (https: //wiki.haskell. org/Template_Haskell) per generare tale codice Sarebbe ragionevole per il tuo caso d'uso? –