No es posible. Los tipos infinitos (que no son tipos de datos) están explícitamente prohibidos en Haskell, y es fácil producir código que los requiera, y por lo tanto produce un error (por ejemplo, intente let foo = (42, foo) in foo
).
Puede, por supuesto, crearlos con newtype
y data
, como lo hizo, pero luego tiene que envolver y desenvolver explícitamente los valores dentro y fuera de los constructores.
Esta es una decisión de diseño explícita: con infinitos tipos, muchas expresiones obviamente erróneas que quisiéramos que el compilador rechazara deberían permitirse, y dado que se permitirían muchos más programas, muchos programas previamente sin ambigüedad se escribiría ambiguamente, requiriendo anotaciones de tipo explícito. Por lo tanto, se realiza una compensación: exigirle que sea explícito acerca de los usos bastante raros de los tipos infinitos a cambio de obtener mucha más ayuda del sistema de tipos de lo que haríamos de otra manera.
Dicho esto, no es una manera de definir algo similar a la función eat
, utilizando las clases de tipos, pero no puede detener sólo cuando se le da un 3: si le ha dado un 3 o no puede solo se determinará en tiempo de ejecución, y los tipos se deciden en el momento de la compilación. Sin embargo, aquí es un valor de sobrecarga que puede ser tanto un Integer
, y una función que solo se come su argumento:
class Eat a where
eat :: a
instance Eat Integer where
eat = 3
instance (Eat r) => Eat (a -> r) where
eat _ = eat
El problema es que es necesario especificar los tipos precisamente cuando lo utiliza:
*Main> eat 1 foldr()
<interactive>:6:1:
Ambiguous type variable `t0' in the constraint:
(Eat t0) arising from a use of `eat'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: eat 1 foldr()
In an equation for `it': it = eat 1 foldr()
*Main> eat 1 foldr() :: Integer
3
Esto es porque eat 1 foldr()
podría ser Integer
, pero también podría ser otra función, del mismo modo que usamos eat 1
y eat 1 foldr
como funciones en la misma expresión. Nuevamente, obtenemos tipeo flexible, pero tenemos que especificar explícitamente los tipos que queremos a cambio.
Piense clase de tipos sobrecarga, como los literales numéricos sobrecargados (42
puede ser cualquier tipo que es una instancia de Num
).
No hay infinitos tipos en haskell está bien. Quería saber si hay un problema aquí que ** ** técnicamente ** no usa infinitos tipos pero aún funciona – Karan
Expandí mi respuesta justo cuando publicaste ese comentario; Espero que ayude a responder esa pregunta adicional :) – ehird
Entonces, comer siempre devuelve 3, y come cualquier tipo (a -> (b-> .. Entero)) – Karan