("Java", wie hier verwendet, ist als Standard Java SE 7 definiert . "Haskell", wie hier verwendet, ist als Standard Haskell 2010 definiert .)
Dinge, die Javas Typsystem hat, aber Haskells nicht:
- nomineller Subtyp Polymorphismus
- teilweise Laufzeit Typinformationen
Dinge, die das Typensystem von Haskell hat, aber das von Java nicht:
- begrenzter Ad-hoc-Polymorphismus
- führt zu "Constraint-basiertem" Subtyp-Polymorphismus
- höherwertiger parametrischer Polymorphismus
- Haupttypisierung
BEARBEITEN:
Beispiele für jeden der oben aufgeführten Punkte:
Einzigartig für Java (im Vergleich zu Haskell)
Nomineller Subtyp Polymorphismus
/* 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 */
Informationen zum Typ der Teillaufzeit
/* 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'
Einzigartig für Haskell (im Vergleich zu Java)
Eingeschränkter Ad-hoc-Polymorphismus
-- 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")
Polymorphismus des Subtyps "Constraint-based" (basierend auf begrenztem Ad-hoc-Polymorphismus)
-- 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
Höherwertiger parametrischer Polymorphismus
-- 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
Haupttypisierung
Es ist schwierig, ein direktes Beispiel dafür zu geben, aber es bedeutet, dass jeder Ausdruck genau einen maximal allgemeinen Typ (seinen Haupttyp genannt ) hat, der als kanonischer Typ dieses Ausdrucks betrachtet wird. In Bezug auf den Polymorphismus des Subtyps "Constraint-based" (siehe oben) ist der Haupttyp eines Ausdrucks der eindeutige Subtyp jedes möglichen Typs, als den dieser Ausdruck verwendet werden kann. Das Vorhandensein von Principal Typing in (nicht erweitertem) Haskell ermöglicht eine vollständige Typinferenz (dh eine erfolgreiche Typinferenz für jeden Ausdruck, ohne dass Typanmerkungen erforderlich sind). Erweiterungen, die die Haupttypisierung unterbrechen (von denen es viele gibt), unterbrechen auch die Vollständigkeit der Typinferenz.