("Java", tel qu'utilisé ici, est défini en tant que norme Java SE 7 ; "Haskell", tel qu'utilisé ici, est défini en tant que norme Haskell 2010. )
Ce que le système de types de Java a mais que Haskell n'a pas:
- polymorphisme nominal de sous-type
- informations de type d'exécution partielle
Choses que le système de types de Haskell a mais que celles de Java ne:
- polymorphisme ad-hoc lié
- donne lieu à un polymorphisme de sous-type "basé sur des contraintes"
- polymorphisme paramétrique de type supérieur
- dactylographie principale
MODIFIER:
Exemples de chacun des points énumérés ci-dessus:
Unique à Java (par rapport à Haskell)
Polymorphisme nominal de sous-type
/* 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 */
Informations de type d'exécution partielle
/* 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'
Unique à Haskell (par rapport à Java)
Polymorphisme ad hoc limité
-- 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")
Polymorphisme de sous-type "basé sur des contraintes" (basé sur un polymorphisme ad-hoc lié)
-- 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
Polymorphisme paramétrique de type élevé
-- 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
Dactylographie principale
Il est difficile de donner un exemple direct avec celui-ci, mais cela signifie que chaque expression a exactement un type général maximum (appelé son type principal ), qui est considéré comme le type canonique de cette expression. En termes de polymorphisme de sous-type "basé sur la contrainte" (voir ci-dessus), le type principal d'une expression est le sous-type unique de chaque type possible dans lequel cette expression peut être utilisée. La présence d'un typage principal dans Haskell (non étendu) est ce qui permet une inférence de type complète (c'est-à-dire une inférence de type réussie pour chaque expression, sans aucune annotation de type nécessaire). Les extensions qui rompent le typage principal (il en existe beaucoup) cassent également la complétude de l'inférence de type.