What does the `forall` keyword in Haskell/GHC do?

前端 未结 8 1503
[愿得一人]
[愿得一人] 2020-11-28 17:01

I\'m beginning to understand how the forall keyword is used in so-called \"existential types\" like this:

data ShowBox = forall s. Show s =>          


        
相关标签:
8条回答
  • 2020-11-28 17:51

    The reason why there are different uses of this keyword is that it's actually used in at least two different type system extensions: higher-rank types, and existentials.

    It's probably best just to read about and understand those two things separately, rather than trying to get an explanation of why 'forall' is an appropriate bit of syntax in both at the same time.

    0 讨论(0)
  • 2020-11-28 17:52

    How is existential existential?

    With Existential-Quantification, foralls in data definitions mean that, the value contained can be of any suitable type, not that it must be of all suitable types. -- yachiru's answer

    An explanation of why forall in data definitions are isomorphic to (exists a. a) (pseudo-Haskell) can be found in wikibooks's "Haskell/Existentially quantified types".

    The following is a brief verbatim summary:

    data T = forall a. MkT a -- an existential datatype
    MkT :: forall a. a -> T -- the type of the existential constructor
    

    When pattern-matching/deconstructing MkT x, what is the type of x?

    foo (MkT x) = ... -- -- what is the type of x?
    

    x can be any type (as stated in the forall), and so it's type is:

    x :: exists a. a -- (pseudo-Haskell)
    

    Therefore, the following are isomorphic:

    data T = forall a. MkT a -- an existential datatype
    data T = MkT (exists a. a) -- (pseudo-Haskell)
    

    forall means forall

    My simple interpretation of all this, is that "forall really means 'for all'". An important distinction to make is the impact of forall on the definition versus function application.

    A forall means the definition of the value or function must be polymorphic.

    If the thing being defined is a polymorphic value, then it means that the value must be valid for all suitable a, which is quite restrictive.

    If the thing being defined is a polymorphic function, then it means that the function must be valid for all suitable a, which isn't that restrictive because just because the function is polymorphic doesn't mean the parameter being applied have to be polymorphic. That is, if the function is valid for all a, then conversely any suitable a can be applied to the function. However, the type of the parameter can only be chosen once in the function definition.

    If a forall is inside the function parameter's type (i.e., a Rank2Type) then it means the applied parameter must be truly polymorphic, to be consistent with the idea of forall means definition is polymorphic. In this case, the type of the parameter can be chosen more than once in the function definition ("and is chosen by the implementation of the function", as pointed out by Norman)

    Therefore, the reason why existential data definitions allows any a is because the data constructor is a polymorphic function:

    MkT :: forall a. a -> T
    

    kind of MkT :: a -> *

    Which means any a may be applied to the function. As opposed to, say, a polymorphic value:

    valueT :: forall a. [a]
    

    kind of valueT :: a

    Which means that the definition of valueT must be polymorphic. In this case, valueT can be defined as empty list [] of all types.

    [] :: [t]
    

    Differences

    Even though the meaning for forall is consistent in ExistentialQuantification and RankNType, existentials has a difference since the data constructor can be used in pattern matching. As documented in the ghc user guide:

    When pattern matching, each pattern match introduces a new, distinct, type for each existential type variable. These types cannot be unified with any other type, nor can they escape from the scope of the pattern match.

    0 讨论(0)
提交回复
热议问题