Frage

Wenn Typ X ist wie folgt definiert:

data X = 
    X { sVal :: String } |
    I { iVal :: Int } |
    B { bVal :: Bool }

und ich möchte die Int innerhalb eines X Wert, wenn es einen gibt, sonst Null.

returnInt :: X -> Int

Wie kann ich, welche Art von X bestimmen das Argument returnInt ist?

War es hilfreich?

Lösung

Nur einen Punkt hier zu klären, lassen Sie mich Ihren Datentyp umschreiben Zweideutigkeiten in der Bedeutung von X zu vermeiden:

data SomeType = X { myString :: String} | I {myInt :: Int} | B {myBool :: Bool}

In dieser Definition gibt es keine X, I und B-Typen. X, I und B sind Konstruktoren, die einen Wert vom Typ Sometype erstellen. Beachten Sie, was passiert, wenn Sie GHCI fragen, was die Art von Wert mit diesen Typkonstruktoren aufgebaut ist:

*Main> :t (I 5)
(I 5) :: Sometype 

*Main> :t (B False)
(B False) :: Sometype

Sie gehören zur gleichen Art !!

Wie Sie X verwenden können, I und B-Typen zu konstruieren, können Sie Muster wie in den anderen Antworten getan verwenden Anpassung der Art dekonstruieren, oben:

returnInt :: SomeType -> Int 
returnInt (I x) = x        -- if the pattern matches (I x) then return x
returnInt _  = error "I need an integer value, you moron"  -- throw an error otherwise

Bitte beachten Sie, dass Mustervergleich erfolgt, um:., Wenn der Wert das Muster in irgendeiner Zeile übereinstimmt, werden die Muster in den Zeilen unter dem nicht ausgeführt werden

Beachten Sie, dass, wenn Sie Ihre Art definieren wie Sie haben, mit was Rekord Syntax aufgerufen wird (nur hier: http://en.wikibooks.org/wiki/Haskell/More_on_datatypes ), haben Sie Funktionen wie das kostenlos !!

Versuchen Sie, auf die Art der myInt, zum Beispiel suchen:

*Main> :t myInt
myInt :: SomeType -> Int

Und schauen, was diese Funktion tun:

*Main> myInt (I 5)
5

*Main> myInt (B False)
*** Exception: No match in record selector Main.myInt

Das ist genau das Verhalten von returnInt oben definiert ist. Die seltsame Fehlermeldung sagt Ihnen, nur, dass die Funktion nicht wissen, wie mit einem Mitglied des Typ Sometype beschäftigen, die nicht (I x) entsprechen.

Wenn Sie Ihre Art mit der häufigeren Syntax definieren:

data SomeType2 = X String | I Int | B Bool

dann verlieren Sie die schönen Aufnahmefunktionen.

Die Fehlermeldungen, die Ausführung des Programms beenden. Das ist manchmal ärgerlich. Wenn Sie sicherer Verhalten für Ihre Funktionen Antwort GBacon die brauchen, ist nur die Art und Weise, es zu tun. Erfahren Sie mehr über die Maybe a Typ und verwenden Sie es mit dieser Art von Berechnung fertig zu werden, die einen Wert zurückgeben müssen oder zurückgeben nichts (versuchen Sie dies: http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe ).

Andere Tipps

Mit Mustervergleich.

returnInt :: X -> Int
returnInt (I x) = x
returnInt _     = 0

Verwenden Sie eine flexiblere Definition für alle möglichen X Werte:

returnInt :: X -> Maybe Int
returnInt (I i) = Just i
returnInt _ = Nothing

Dann können Sie verwenden maybe für die jeweilige säumige Sie wollen-0 könnte einen gültigen Wert sein (dies ist als der semipredicate Problem ):

*Main> maybe 0 id (returnInt $ X "")
0
*Main> maybe 0 id (returnInt $ I 123)
123
*Main> maybe (-1) id (returnInt $ X "yo")
-1

Im Gegensatz dazu Teilfunktionen Risikolaufzeit Ausnahmen:

*Main> let returnInt (I i) = i
*Main> :t returnInt
returnInt :: X -> Int
*Main> returnInt (B True)
*** Exception: <interactive>:1:4-22: Non-exhaustive patterns in function returnInt

Wenn Sie wirklich Froggy Gefühl sind, können Sie MonadPlus verwenden

returnInt :: (MonadPlus m) => X -> m Int
returnInt (I i) = return i
returnInt _ = mzero

gewinnen noch mehr Flexibilität:

*Main> maybe 0 id (returnInt $ X "")
0
*Main> maybe 0 id (returnInt $ I 123)
123
*Main> returnInt (I 123) `mplus` returnInt (I 456) :: [Int]
[123,456]

Bei einer Funktion wie folgt aus:

returnInt :: X -> Int
returnInt x = {- some integer -}

... die Art der x immer X. Was Sie wichtig ist, ob x verwendet den X, I oder B Typkonstruktor.

Mit Mustervergleich den Unterschied zu erkennen:

returnInt :: X -> Int
returnInt (X _) = error "needed an Int, got a String"
returnInt (I { iVal = n }) = n
returnInt (B _) = error "needed an Int, got a Bool"
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top