summaryrefslogtreecommitdiff
path: root/docs/users_guide/exts/type_applications.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/users_guide/exts/type_applications.rst')
-rw-r--r--docs/users_guide/exts/type_applications.rst83
1 files changed, 82 insertions, 1 deletions
diff --git a/docs/users_guide/exts/type_applications.rst b/docs/users_guide/exts/type_applications.rst
index d86b4854ae..08aeb8e9e5 100644
--- a/docs/users_guide/exts/type_applications.rst
+++ b/docs/users_guide/exts/type_applications.rst
@@ -4,7 +4,7 @@ Visible type application
========================
.. extension:: TypeApplications
- :shortdesc: Enable type application syntax in terms and types.
+ :shortdesc: Enable type application syntax in terms, patterns and types.
:since: 8.0.1
@@ -29,6 +29,10 @@ GHC also permits visible kind application, where users can declare the kind
arguments to be instantiated in kind-polymorphic cases. Its usage parallels
visible type application in the term level, as specified above.
+In addition to visible type application in terms and types, the type application
+syntax can be used in patterns matching a data constructor to bind type variables
+in that constructor's type.
+
.. _inferred-vs-specified:
Inferred vs. specified type variables
@@ -274,3 +278,80 @@ of equality over types. For example, given the following definitions: ::
GHC will deem all of ``app1 id1``, ``app1 id2``, ``app2 id1``, and ``app2 id2``
to be well typed.
+
+.. _type-applications-in-patterns:
+
+Type Applications in Patterns
+-----------------------------
+
+The type application syntax can be used in patterns that match a data
+constructor. The syntax can't be used with record patterns or infix patterns.
+This is useful in particular to bind existential type variables associated with
+a GADT data constructor as in the following example::
+
+ {-# LANGUAGE AllowAmbiguousTypes #-}
+ {-# LANGUAGE GADTs #-}
+ {-# LANGUAGE RankNTypes #-}
+ {-# LANGUAGE TypeApplications #-}
+ import Data.Proxy
+
+ data Foo where
+ Foo :: forall a. (Show a, Num a) => Foo
+
+ test :: Foo -> String
+ test x = case x of
+ Foo @t -> show @t 0
+
+ main :: IO ()
+ main = print $ test (Foo @Float)
+
+In this example, the case in ``test``` is binding an existential variable introduced
+by ``Foo`` that otherwise could not be named and used.
+
+It's possible to bind variables to any part of the type arguments to a constructor;
+there is no need for them to be existential. In addition, it's possible to "match" against
+part of the type argument using type constructors.
+
+For a somewhat-contrived example::
+
+ foo :: (Num a) => Maybe [a] -> String
+ foo (Nothing @[t]) = show (0 :: t)
+ foo (Just @[t] xs) = show (sum xs :: t)
+
+Here, we're binding the type variable t to be the type of the elements of the list type
+which is itself the argument to Maybe.
+
+The order of the type arguments specified by the type applications in a pattern is the same
+as that for an expression: either the order as given by the user in an explicit ``forall`` in the
+definition of the data constructor, or if that is not present, the order in which the type
+variables appear in its type signature from left to right.
+
+For example if we have the following declaration in GADT syntax::
+
+ data Foo :: * -> * where
+ A :: forall s t. [(t,s)] -> Foo (t,s)
+ B :: (t,s) -> Foo (t,s)
+
+Then the type arguments to ``A`` will match first ``s`` and then ``t``, while the type arguments
+to ``B`` will match first ``t`` and then ``s``.
+
+Type arguments appearing in patterns can influence the inferred type of a definition::
+
+ foo (Nothing @Int) = 0
+ foo (Just x) = x
+
+will have inferred type::
+
+ foo :: Maybe Int -> Int
+
+which is more restricted than what it would be without the application::
+
+ foo :: Num a => Maybe a -> a
+
+For more information and detail regarding type applications in patterns, see the paper
+`Type variables in patterns <https://arxiv.org/pdf/1806.03476>`__ by Eisenberg, Breitner
+and Peyton Jones. Relative to that paper, the implementation in GHC for now at least makes one
+additional conservative restriction, that type variables occurring in patterns must not
+already be in scope, and so are always new variables that only bind whatever type is
+matched, rather than ever referring to a variable from an outer scope. Type wildcards
+``_`` may be used in any place where no new variable needs binding.