On Thu, Aug 19, 2021, at 06:14, Simon Peyton Jones wrote:| We use types to communicate the externally-visible behavior of our| programs: the number of arguments to a function and their types, effects| incurred in the form of monads, etc. Why should liftedness and the| implications for evaluation strategies be different?We use them to *communicate* behaviour, but not to *specify* behaviour.That is done by the definition of the function itself.I disagree, types are a great specification language. The whole point of advancedtype system features is to enhance the specification language so we canspecify more interesting properties.Often, we do this so that the type checker can *verify* our code, but there are plentyof cases where we use types to *drive code generation*. Consider GHC.Generics.We can write a highly-polymorphic JSON serialization functiongToJSON :: Generic a => a -> JSONwhich we can then instantiate at different types, e.g.data FoofooToJSON :: Foo -> JSONfooToJSON = gToJSONdata BarbarToJSON :: Bar -> JSONbarToJSON = gToJSONfooToJSON and barToJSON have the exact same definition, but very differentsemantics. Their complete semantics depends on *both* their definition *and*their type signatures.I think the deeper point here is that Haskell's dynamic semantics depends onits static semantics. We can't evaluate a Haskell program without knowing thetypes involved.