As you see therefore SML is a typed-functional language and the types are not given outright as it happens in some strongly typed languages but they are synthesised by the compiler. SML has a polymorphic-type system. Each legal phrase has a uniquely determined, most general typing that determines the context in which that phrase can be legally used. And this is a good trade off between the rigidity of strong typing and the disdain for safety of type-free languages. What is this polymorphic-type discipline? Well, just think about an algorithm like MAP up here. It does not really function like MAP, it does not really need to know what is the nature of the arguments of the list. Neither the nature of the values that F is going to produce. The only thing that really matters in this case is that MAP takes its first arguments a function no matter what its type is and the second argument a list, but this time such that the elements of the list belong to the domain of the function. SML also supports abstract data types. New types. What are abstract data types? These are new types together with a set of operations on the objects of that type are hidden to the user. And this is very useful for programme modularization. Here the canonical example would be the implementation of sets using lists or using lists with repetitions. You are not really interested to know how the computer has implemented, how the programmer has implemented the notion of set provided you have available an interface for manipulating such objects, an interface with a union function, a test membership function and so on.
SML is statically scoped and also, as we said earlier, expressions in SML are evaluated by value. SML has automatic garbage collection and it is not only a functional language but it has some non-functional features, for instance it has a type-safe management of reference types because functional programming has its merits but imperative programming is here to stay especially in managing state.