¿Hay alguna herramienta que pueda ayudarme a evitar este tipo de error?
No, pero podría haber.
Como sabe, la sintaxis del registro genera automáticamente captadores con el mismo nombre que los atributos que define. Por lo tanto el código
data Person = Adult { pName :: String}
| Kid { pName :: String
, pAge :: Int
} deriving Show
crea las funciones pName :: Person -> String
y pAge :: Person -> Int
. Ahora, supongamos que Haskell tenía subtipos. Si así fuera, entonces Kid
podría ser un subtipo de Person
, y pAge
podría tener el tipo más apropiado Kid -> String
. Sin embargo, Haskell tiene no tiene subtipado, y por lo tanto no hay Kid
tipo.
Ahora, dado que Person -> String
es el tipo más específico que podemos dar a pAge
, ¿por qué no advertir que pAge
es una función parcial en tiempo de compilación? Permítanme Desviar la cuestión haciendo referencia al ejemplo de lista
data List a = Cons { head :: a, tail :: List a } | Empty
En este ejemplo, head
y tail
son funciones parciales: los dos componentes de una lista no vacía, pero (debido a la falta de subtipos de Haskell) descriptores de acceso sin sentido en la lista vacía Entonces, ¿por qué no hay advertencia por defecto? Bueno, de manera predeterminada, conoces el código que has escrito. El compilador no proporciona advertencias si usa unsafePerformIO
, porque usted es el programador aquí, se espera que use esas cosas de manera responsable.
Así tl; dr: si desea que la advertencia aquí:
getAge :: Person -> Int
getAge p = pAge p
entonces estás de suerte, ya que el sistema de tipo no tiene suficiente información para deducir que este es un problema.
Si desea que la advertencia aquí:
data Person = Adult | Kid { pAge :: Int }
entonces estoy seguro de que sería trivial para aplicar: basta con comprobar que existe un campo dado en algunos constructores, pero otros no. Pero no preveo que esta advertencia sea ampliamente útil para todos; algunos podrían quejarse de que sería solo ruido.
Apuesto a que la gente de GHC estaría dispuesta a poner una advertencia para esto. Debe presentar una solicitud de función en [Trac] (http://hackage.haskell.org/trac/ghc/newticket?type=feature+request). –
Hay un sentimiento general de insatisfacción alrededor de los registros en su forma actual. Algunas personas están investigando alternativas. Mientras tanto, los registros de múltiples constructores no son recomendables, y deberían ser una advertencia propia :-) –
http://hackage.haskell.org/trac/ghc/ticket/7169 - puede agregarse a la CC. – sdcvvc