("Java", como se usa aquí, se define como Java SE 7 estándar ; "Haskell", como se usa aquí, se define como Haskell 2010 estándar ).
Cosas que tiene el sistema de tipos de Java pero que Haskell no:
- subtipo nominal polimorfismo
- información de tipo de tiempo de ejecución parcial
Cosas que tiene el sistema de tipos de Haskell pero que Java no tiene:
- polimorfismo ad-hoc acotado
- da lugar a un polimorfismo de subtipo "basado en restricciones"
- polimorfismo paramétrico de tipo superior
- mecanografía principal
EDITAR:
Ejemplos de cada uno de los puntos enumerados anteriormente:
Exclusivo de Java (en comparación con Haskell)
Subtipo nominal de polimorfismo
/* declare explicit subtypes (limited multiple inheritance is allowed) */
abstract class MyList extends AbstractList<String> implements RandomAccess {
/* specify a type's additional initialization requirements */
public MyList(elem1: String) {
super() /* explicit call to a supertype's implementation */
this.add(elem1) /* might be overridden in a subtype of this type */
}
}
/* use a type as one of its supertypes (implicit upcasting) */
List<String> l = new ArrayList<>() /* some inference is available for generics */
Información de tipo de tiempo de ejecución parcial
/* find the outermost actual type of a value at runtime */
Class<?> c = l.getClass // will be 'java.util.ArrayList'
/* query the relationship between runtime and compile-time types */
Boolean b = l instanceOf MyList // will be 'false'
Exclusivo de Haskell (en comparación con Java)
Polimorfismo ad-hoc acotado
-- declare a parametrized bound
class A t where
-- provide a function via this bound
tInt :: t Int
-- require other bounds within the functions provided by this bound
mtInt :: Monad m => m (t Int)
mtInt = return tInt -- define bound-provided functions via other bound-provided functions
-- fullfill a bound
instance A Maybe where
tInt = Just 5
mtInt = return Nothing -- override defaults
-- require exactly the bounds you need (ideally)
tString :: (Functor t, A t) => t String
tString = fmap show tInt -- use bounds that are implied by a concrete type (e.g., "Show Int")
Polimorfismo de subtipo "basado en restricciones" (basado en polimorfismo ad-hoc acotado)
-- declare that a bound implies other bounds (introduce a subbound)
class (A t, Applicative t) => B t where -- bounds don't have to provide functions
-- use multiple bounds (intersection types in the context, union types in the full type)
mtString :: (Monad m, B t) => m (t String)
mtString = return mtInt -- use a bound that is implied by another bound (implicit upcasting)
optString :: Maybe String
optString = join mtString -- full types are contravariant in their contexts
Polimorfismo paramétrico de tipo superior
-- parametrize types over type variables that are themselves parametrized
data OneOrTwoTs t x = OneVariableT (t x) | TwoFixedTs (t Int) (t String)
-- bounds can be higher-kinded, too
class MonadStrip s where
-- use arbitrarily nested higher-kinded type variables
strip :: (Monad m, MonadTrans t) => s t m a -> t m a -> m a
Mecanografía principal
Es difícil dar un ejemplo directo de este, pero significa que cada expresión tiene exactamente un tipo máximo general (llamado su tipo principal ), que se considera el tipo canónico de esa expresión. En términos de polimorfismo de subtipo "basado en restricciones" (ver arriba), el tipo principal de una expresión es el subtipo único de cada tipo posible en el que se puede usar esa expresión. La presencia de tipeo principal en Haskell (no extendido) es lo que permite una inferencia de tipo completa (es decir, una inferencia de tipo exitosa para cada expresión, sin necesidad de anotaciones de tipo). Las extensiones que rompen la tipificación principal (de las cuales hay muchas) también rompen la integridad de la inferencia de tipos.