("Java", como usado aqui, é definido como padrão Java SE 7 ; "Haskell", como usado aqui, é definido como padrão Haskell 2010 .
Coisas que o sistema de tipos do Java tem, mas as do Haskell não:
- polimorfismo de subtipo nominal
- informações do tipo em tempo de execução parcial
Coisas que o sistema de tipos de Haskell tem, mas que o Java não possui:
- polimorfismo ad-hoc limitado
- dá origem ao polimorfismo de subtipo "baseado em restrição"
- polimorfismo paramétrico de maior qualidade
- digitação principal
EDITAR:
Exemplos de cada um dos pontos listados acima:
Exclusivo para Java (em comparação com o Haskell)
Polimorfismo de subtipo nominal
/* 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 */
Informações do tipo de tempo de execução 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 para o Haskell (em comparação com o Java)
Polimorfismo ad-hoc limitado
-- 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 "baseado em restrições" (baseado em polimorfismo ad-hoc limitado)
-- 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 maior qualidade
-- 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
Digitação principal
Este é difícil de dar um exemplo direto, mas significa que toda expressão tem exatamente um tipo maximalmente geral (chamado de tipo principal ), que é considerado o tipo canônico daquela expressão. Em termos de polimorfismo de subtipo "baseado em restrição" (ver acima), o tipo principal de uma expressão é o subtipo único de cada tipo possível para o qual essa expressão pode ser usada. A presença de digitação principal (não estendida) Haskell é o que permite a inferência de tipos completa (isto é, inferência de tipo bem-sucedida para cada expressão, sem qualquer tipo de anotação necessária). Extensões que quebram a digitação principal (que são muitas) também quebram a integridade da inferência de tipos.