{- | Module : MyType Description : Type applications Copyright : © Frank Jung, 2022-2025 License : GPL-3 = Key Concepts Used == Type Applications This feature allows you to explicitly specify types in your code using the @ syntax. For example, typeName @Int explicitly applies the type Int to the function typeName. == Ambiguous Types Ambiguous types occur when the type system cannot infer a type parameter because it is not used in a way that provides enough information. For example, in typeName, the type parameter a is only used in the phantom type of Proxy, which doesn't provide enough information for inference. == Scoped Type Variables The ScopedTypeVariables extension allows type variables declared in a forall to be used explicitly within the function body. == Typeable The Typeable typeclass provides runtime type information. The typeRep function retrieves a representation of a type that can be converted to a string. -} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} module MyType (typeName) where import Data.Data (Typeable, typeRep) import Data.Proxy (Proxy (..)) -- | Proxy to record type. Proxy is equivalent to the unit type, @()@. But -- also has a phantom type parameter @a@, which is used to keep track of -- the type. -- (Use type from `Data.Proxy`) -- data Proxy a = Proxy -- | Show ambigous types. -- Hindley-Milner type system can only infer types to the right of the -- context arrow (@=>@), which means the type parameter @a@ can never be -- correctly inferred. Haskell refers to such a type as /ambiguous/. -- -- [Proxy @a]: Creates a Proxy value with the phantom type @a@. A Proxy is a -- placeholder that carries type information but has no runtime value. -- -- [typeRep $ Proxy @a]: Retrieves the runtime representation of the type @a@ -- using @typeRep@. -- -- [show]: Converts the type representation to a string. -- -- >>> typeName @Int -- "Int" -- -- >>> typeName @String -- "[Char]" -- -- >>> typeName @(Maybe [Int]) -- "Maybe [Int]" typeName :: forall a. Typeable a => String typeName :: forall a. Typeable a => String typeName = TypeRep -> String forall a. Show a => a -> String show (TypeRep -> String) -> (Proxy a -> TypeRep) -> Proxy a -> String forall b c a. (b -> c) -> (a -> b) -> a -> c . Proxy a -> TypeRep forall {k} (proxy :: k -> *) (a :: k). Typeable a => proxy a -> TypeRep typeRep (Proxy a -> String) -> Proxy a -> String forall a b. (a -> b) -> a -> b $ forall t. Proxy t forall {k} (t :: k). Proxy t Proxy @a