Pregunta

Cuando el tipo de X se define como:

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

y quiero que el Int dentro de un valor X, si es que existe, de lo contrario cero.

returnInt :: X -> Int

¿Cómo puedo determinar qué tipo de X el argumento a returnInt es?

¿Fue útil?

Solución

Solo para aclarar un punto aquí, déjame volver a escribir el tipo de datos para evitar ambigüedades en el significado de X:

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

En esta definición no hay X, tipos I y B. X, I y B son constructores que crean un valor de tipo Sometype. Tenga en cuenta lo que sucede cuando se pregunta ghci lo que es el tipo de cualquier valor calculado con los constructores de tipo:

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

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

Pertenecen al mismo tipo !!

Al igual que puede utilizar X, I y B para la construcción de tipos, puede utilizar coincidencia de patrones para deconstruir el tipo, al igual que hizo en las otras respuestas anteriores:

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

Sólo recuerde que la coincidencia de patrones se produce en orden:. Si el valor coincide con el patrón en alguna línea, no se ejecutarán los patrones de líneas por debajo de ese

Tenga en cuenta que cuando se define el tipo como lo hizo, utilizando lo que se denomina Registro de sintaxis (con tan sólo mirar aquí: http://en.wikibooks.org/wiki/Haskell/More_on_datatypes ), que tiene funciones como la de forma gratuita !!

Trate de buscar en el tipo de myInt, por ejemplo:

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

Y mira lo que hace esta función:

*Main> myInt (I 5)
5

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

Este es exactamente el comportamiento de returnInt se ha definido anteriormente. El mensaje de error extraño sólo le dice que la función no saben cómo hacer frente a un miembro de la SomeType tipo que no coincide con (I x).

Si se define el tipo de uso de la sintaxis más comunes:

data SomeType2 = X String | I Int | B Bool

, perderá esas bonitas funciones de grabación.

Los mensajes de error terminar la ejecución del programa. Esto es molesto a veces. Si necesita un comportamiento más seguro para sus funciones de respuesta de GBacon es sólo la manera de hacerlo. Aprender sobre el tipo Maybe a y lo utilizan para hacer frente a este tipo de computación que necesita volver algún valor o nada de retorno (intente esto: http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe ).

Otros consejos

Uso coincidencia de patrones.

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

Utilice una definición más flexible para todos los posibles valores de X:

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

A continuación, puede utilizar maybe para el incumplimiento en particular que desea-0 puede ser un valor válido (esto se conoce como la semipredicate problema ):

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

Por el contrario, funciones parciales excepciones de tiempo de ejecución de riesgo:

*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

Si se siente realmente froggy, podría utilizar MonadPlus

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

para ganar aún más flexibilidad:

*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]

Dada una función como esta:

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

... del tipo de x siempre se X. Lo que importa es si x utiliza el X, I o B de tipo constructor.

El uso de coincidencia de patrones de notar la diferencia:

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"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top