Wie andere angegeben haben, wie angegeben, hat dieses Problem keine Lösung. Aber Ihr wirkliches Problem ist, dass Ihre Daten nicht durch eine Liste von Tupeln beschrieben werden - per Definition ist eine Liste homogen (alle Elemente enthalten den gleichen Typ), während Ihre Daten heterogen sind.
Wenn Sie eine Funktion abhängig vom Typ schreiben möchten, müssen Sie den Typ irgendwie auf der Typenebene speichern.
Ihre Beispieldaten werden beschrieben tatsächlich vom Typ Prod ((,) Integer) '[String, Bool, Integer]
, wo Prod
der folgende Typ ist:
data Prod f (xs :: [a]) where
P0 :: Prod f '[]
(:>) :: f x -> Prod f xs -> Prod f (x ': xs)
infixr 5 :>
oder allgemeine Prod ((,) Integer) xs
für einige Liste der Typen xs
.
Ihr Beispiel Wert ist dann
a = (1, "uno") :> (2, True) :> (3, 5) :> P0
Sie können auf diese Art verzweigen die normalen Methoden - das heißt eine Typklasse. Angenommen man hat eine solche Klasse:
class HasFoo x where
foo :: x -> Integer
instance HasFoo String where foo = fromIntegral . length
instance HasFoo Bool where foo = fromIntegral . fromEnum
instance HasFoo Integer where foo = id
Sie anwenden können, eine solche foo
Funktion auf jedes Element Ihres Produktes
type family All (c :: k -> Constraint) (xs :: [k]) :: Constraint where
All c '[] =()
All c (x ': xs) = (c x, All c xs)
-- example operation: add everything
fooProd :: All HasFoo xs
=> Prod ((,) Integer) xs
-> Integer
fooProd P0 = 0
fooProd ((i, x) :> ps) = i + foo x + fooProd ps
Dieses einige GHC Erweiterungen erfordert, mindestens TypeFamilies
, GADTs
, ConstraintKinds
, DataKinds
, PolyKinds
.
Ich glaube nicht, dass dies derzeit ohne die ImpredicativeTypes-Erweiterung möglich ist, die derzeit [nicht wirklich funktioniert] (http://stackoverflow.com/q/33741334/465378). –
@AlexisKing 'ImpredicativeTypes' wird dir hier nicht helfen. Impredicativity ermöglicht die Parametrisierung von Typen durch 'forall'-quantifizierte Typen, zB um eine _homogene_ Liste von polymorphen Funktionen zu erstellen. OP möchte eine heterogene Liste von monomorphen Tupeln erstellen. –
@jonaprieto Was versuchst du zu erreichen? Der einfachste Weg besteht darin, einen Summen-Typ zu erstellen und eine Laufzeit-Analyse auf den Werten zu machen: 'a :: [(Int, Boole String)]' –