openapi3-3.2.4: OpenAPI 3.0 data model
Safe HaskellSafe-Inferred
LanguageHaskell2010

Data.OpenApi.Internal.Schema

Synopsis

Documentation

>>> import Data.Aeson.Types (toJSONKeyText)
>>> import qualified Data.ByteString.Lazy.Char8 as BSL
>>> import Data.OpenApi.Internal
>>> import Data.OpenApi.Internal.Utils (encodePretty)
>>> import Data.OpenApi.Lens (name, schema)

class Typeable a => ToSchema a where Source #

Convert a type into Schema.

An example type and instance:

{-# LANGUAGE OverloadedStrings #-}   -- allows to write Text literals
{-# LANGUAGE OverloadedLists #-}     -- allows to write Map and HashMap as lists

import Control.Lens
import Data.Proxy
import Data.OpenApi

data Coord = Coord { x :: Double, y :: Double }

instance ToSchema Coord where
  declareNamedSchema _ = do
    doubleSchema <- declareSchemaRef (Proxy :: Proxy Double)
    return $ NamedSchema (Just "Coord") $ mempty
      & type_ ?~ OpenApiObject
      & properties .~
          [ ("x", doubleSchema)
          , ("y", doubleSchema)
          ]
      & required .~ [ "x", "y" ]

Instead of manually writing your ToSchema instance you can use a default generic implementation of declareNamedSchema.

To do that, simply add deriving Generic clause to your datatype and declare a ToSchema instance for your datatype without giving definition for declareNamedSchema.

For instance, the previous example can be simplified into this:

{-# LANGUAGE DeriveGeneric #-}

import GHC.Generics (Generic)

data Coord = Coord { x :: Double, y :: Double } deriving Generic

instance ToSchema Coord

Minimal complete definition

Nothing

Methods

declareNamedSchema :: Proxy a -> Declare (Definitions Schema) NamedSchema Source #

Convert a type into an optionally named schema together with all used definitions. Note that the schema itself is included in definitions only if it is recursive (and thus needs its definition in scope).

Instances

Instances details
ToSchema Object Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema All Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Any Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Version Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Int16 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Int32 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Int64 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Int8 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Word16 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Word32 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Word64 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Word8 Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchemaByteStringError ByteString :: Constraint) => ToSchema ByteString Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchemaByteStringError ByteString :: Constraint) => ToSchema ByteString Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema IntSet Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Scientific Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Text Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Text Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Day Source #

Format "date" corresponds to yyyy-mm-dd format.

Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema NominalDiffTime Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema UTCTime Source #
>>> toSchema (Proxy :: Proxy UTCTime) ^. format
Just "yyyy-mm-ddThh:MM:ssZ"
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema LocalTime Source #
>>> toSchema (Proxy :: Proxy LocalTime) ^. format
Just "yyyy-mm-ddThh:MM:ss"
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema TimeOfDay Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema ZonedTime Source #

Format "date-time" corresponds to yyyy-mm-ddThh:MM:ss(Z|+hh:MM) format.

Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema UUID Source #

For ToJSON instance, see uuid-aeson package.

Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema String Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Integer Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Natural Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema () Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Bool Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Char Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Double Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Float Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Int Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema Word Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Identity a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (First a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Last a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Dual a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Product a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Sum a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (NonEmpty a) Source #

Since: 2.2.1

Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (IntMap a) Source #

NOTE: This schema does not account for the uniqueness of keys.

Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Set a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (HashSet a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Vector a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Vector a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Vector a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Vector a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema (Maybe a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema a => ToSchema [a] Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b) => ToSchema (Either a b) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(Typeable (Fixed a), HasResolution a) => ToSchema (Fixed a) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (Map k v) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToJSONKey k, ToSchema k, ToSchema v) => ToSchema (HashMap k v) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b) => ToSchema (a, b) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b, ToSchema c) => ToSchema (a, b, c) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b, ToSchema c, ToSchema d) => ToSchema (a, b, c, d) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e) => ToSchema (a, b, c, d, e) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f) => ToSchema (a, b, c, d, e, f) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(ToSchema a, ToSchema b, ToSchema c, ToSchema d, ToSchema e, ToSchema f, ToSchema g) => ToSchema (a, b, c, d, e, f, g) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

Methods

declareNamedSchema :: Proxy (a, b, c, d, e, f, g) -> Declare (Definitions Schema) NamedSchema Source #

declareSchema :: ToSchema a => Proxy a -> Declare (Definitions Schema) Schema Source #

Convert a type into a schema and declare all used schema definitions.

toNamedSchema :: ToSchema a => Proxy a -> NamedSchema Source #

Convert a type into an optionally named schema.

>>> toNamedSchema (Proxy :: Proxy String) ^. name
Nothing
>>> BSL.putStrLn $ encodePretty (toNamedSchema (Proxy :: Proxy String) ^. schema)
{
    "type": "string"
}
>>> toNamedSchema (Proxy :: Proxy Day) ^. name
Just "Day"
>>> BSL.putStrLn $ encodePretty (toNamedSchema (Proxy :: Proxy Day) ^. schema)
{
    "example": "2016-07-22",
    "format": "date",
    "type": "string"
}

schemaName :: ToSchema a => Proxy a -> Maybe Text Source #

Get type's schema name according to its ToSchema instance.

>>> schemaName (Proxy :: Proxy Int)
Nothing
>>> schemaName (Proxy :: Proxy UTCTime)
Just "UTCTime"

toSchema :: ToSchema a => Proxy a -> Schema Source #

Convert a type into a schema.

>>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy Int8)
{
    "maximum": 127,
    "minimum": -128,
    "type": "integer"
}
>>> BSL.putStrLn $ encodePretty $ toSchema (Proxy :: Proxy [Day])
{
    "items": {
        "$ref": "#/components/schemas/Day"
    },
    "type": "array"
}

toSchemaRef :: ToSchema a => Proxy a -> Referenced Schema Source #

Convert a type into a referenced schema if possible. Only named schemas can be referenced, nameless schemas are inlined.

>>> BSL.putStrLn $ encodePretty $ toSchemaRef (Proxy :: Proxy Integer)
{
    "type": "integer"
}
>>> BSL.putStrLn $ encodePretty $ toSchemaRef (Proxy :: Proxy Day)
{
    "$ref": "#/components/schemas/Day"
}

declareSchemaRef :: ToSchema a => Proxy a -> Declare (Definitions Schema) (Referenced Schema) Source #

Convert a type into a referenced schema if possible and declare all used schema definitions. Only named schemas can be referenced, nameless schemas are inlined.

Schema definitions are typically declared for every referenced schema. If declareSchemaRef returns a reference, a corresponding schema will be declared (regardless of whether it is recusive or not).

inlineSchemasWhen :: Data s => (Text -> Bool) -> Definitions Schema -> s -> s Source #

Inline any referenced schema if its name satisfies given predicate.

NOTE: if a referenced schema is not found in definitions the predicate is ignored and schema stays referenced.

WARNING: inlineSchemasWhen will produce infinite schemas when inlining recursive schemas.

inlineSchemas :: Data s => [Text] -> Definitions Schema -> s -> s Source #

Inline any referenced schema if its name is in the given list.

NOTE: if a referenced schema is not found in definitions it stays referenced even if it appears in the list of names.

WARNING: inlineSchemas will produce infinite schemas when inlining recursive schemas.

inlineAllSchemas :: Data s => Definitions Schema -> s -> s Source #

Inline all schema references for which the definition can be found in Definitions.

WARNING: inlineAllSchemas will produce infinite schemas when inlining recursive schemas.

toInlinedSchema :: ToSchema a => Proxy a -> Schema Source #

Convert a type into a schema without references.

>>> BSL.putStrLn $ encodePretty $ toInlinedSchema (Proxy :: Proxy [Day])
{
    "items": {
        "example": "2016-07-22",
        "format": "date",
        "type": "string"
    },
    "type": "array"
}

WARNING: toInlinedSchema will produce infinite schema when inlining recursive schemas.

inlineNonRecursiveSchemas :: Data s => Definitions Schema -> s -> s Source #

Inline all non-recursive schemas for which the definition can be found in Definitions.

sketchSchema :: ToJSON a => a -> Schema Source #

Make an unrestrictive sketch of a Schema based on a ToJSON instance. Produced schema can be used for further refinement.

>>> BSL.putStrLn $ encodePretty $ sketchSchema "hello"
{
    "example": "hello",
    "type": "string"
}
>>> BSL.putStrLn $ encodePretty $ sketchSchema (1, 2, 3)
{
    "example": [
        1,
        2,
        3
    ],
    "items": {
        "type": "number"
    },
    "type": "array"
}
>>> BSL.putStrLn $ encodePretty $ sketchSchema ("Jack", 25)
{
    "example": [
        "Jack",
        25
    ],
    "items": [
        {
            "type": "string"
        },
        {
            "type": "number"
        }
    ],
    "type": "array"
}
>>> data Person = Person { name :: String, age :: Int } deriving (Generic)
>>> instance ToJSON Person
>>> BSL.putStrLn $ encodePretty $ sketchSchema (Person "Jack" 25)
{
    "example": {
        "age": 25,
        "name": "Jack"
    },
    "properties": {
        "age": {
            "type": "number"
        },
        "name": {
            "type": "string"
        }
    },
    "required": [
        "age",
        "name"
    ],
    "type": "object"
}

sketchStrictSchema :: ToJSON a => a -> Schema Source #

Make a restrictive sketch of a Schema based on a ToJSON instance. Produced schema uses as much constraints as possible.

>>> BSL.putStrLn $ encodePretty $ sketchStrictSchema "hello"
{
    "enum": [
        "hello"
    ],
    "maxLength": 5,
    "minLength": 5,
    "pattern": "hello",
    "type": "string"
}
>>> BSL.putStrLn $ encodePretty $ sketchStrictSchema (1, 2, 3)
{
    "enum": [
        [
            1,
            2,
            3
        ]
    ],
    "items": [
        {
            "enum": [
                1
            ],
            "maximum": 1,
            "minimum": 1,
            "multipleOf": 1,
            "type": "number"
        },
        {
            "enum": [
                2
            ],
            "maximum": 2,
            "minimum": 2,
            "multipleOf": 2,
            "type": "number"
        },
        {
            "enum": [
                3
            ],
            "maximum": 3,
            "minimum": 3,
            "multipleOf": 3,
            "type": "number"
        }
    ],
    "maxItems": 3,
    "minItems": 3,
    "type": "array",
    "uniqueItems": true
}
>>> BSL.putStrLn $ encodePretty $ sketchStrictSchema ("Jack", 25)
{
    "enum": [
        [
            "Jack",
            25
        ]
    ],
    "items": [
        {
            "enum": [
                "Jack"
            ],
            "maxLength": 4,
            "minLength": 4,
            "pattern": "Jack",
            "type": "string"
        },
        {
            "enum": [
                25
            ],
            "maximum": 25,
            "minimum": 25,
            "multipleOf": 25,
            "type": "number"
        }
    ],
    "maxItems": 2,
    "minItems": 2,
    "type": "array",
    "uniqueItems": true
}
>>> data Person = Person { name :: String, age :: Int } deriving (Generic)
>>> instance ToJSON Person
>>> BSL.putStrLn $ encodePretty $ sketchStrictSchema (Person "Jack" 25)
{
    "enum": [
        {
            "age": 25,
            "name": "Jack"
        }
    ],
    "maxProperties": 2,
    "minProperties": 2,
    "properties": {
        "age": {
            "enum": [
                25
            ],
            "maximum": 25,
            "minimum": 25,
            "multipleOf": 25,
            "type": "number"
        },
        "name": {
            "enum": [
                "Jack"
            ],
            "maxLength": 4,
            "minLength": 4,
            "pattern": "Jack",
            "type": "string"
        }
    },
    "required": [
        "age",
        "name"
    ],
    "type": "object"
}

class GToSchema (f :: * -> *) where Source #

Instances

Instances details
(GToSchema f, GToSchema g) => GToSchema (f :*: g) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(GSumToSchema f, GSumToSchema g) => GToSchema (f :+: g) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(Selector s, GToSchema f, GToSchema (S1 s f)) => GToSchema (C1 c (S1 s f)) Source #

Single field constructor.

Instance details

Defined in Data.OpenApi.Internal.Schema

Constructor c => GToSchema (C1 c (U1 :: Type -> Type)) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

GToSchema f => GToSchema (C1 c f) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(Datatype d, GToSchema f) => GToSchema (D1 d f) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema c => GToSchema (K1 i (Maybe c) :: Type -> Type) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

ToSchema c => GToSchema (K1 i c :: Type -> Type) Source # 
Instance details

Defined in Data.OpenApi.Internal.Schema

(Selector s, ToSchema c) => GToSchema (S1 s (K1 i (Maybe c) :: Type -> Type)) Source #

Optional record fields.

Instance details

Defined in Data.OpenApi.Internal.Schema

(Selector s, GToSchema f) => GToSchema (S1 s f) Source #

Record fields.

Instance details

Defined in Data.OpenApi.Internal.Schema

type family ToSchemaByteStringError bs where ... Source #

Equations

ToSchemaByteStringError bs = TypeError ((((Text "Impossible to have an instance " :<>: ShowType (ToSchema bs)) :<>: Text ".") :$$: ((Text "Please, use a newtype wrapper around " :<>: ShowType bs) :<>: Text " instead.")) :$$: Text "Consider using byteSchema or binarySchema templates.") 

toSchemaBoundedIntegral :: forall a. (Bounded a, Integral a) => Proxy a -> Schema Source #

Default schema for Bounded, Integral types.

>>> BSL.putStrLn $ encodePretty $ toSchemaBoundedIntegral (Proxy :: Proxy Int16)
{
    "maximum": 32767,
    "minimum": -32768,
    "type": "integer"
}

genericToNamedSchemaBoundedIntegral :: forall a d f. (Bounded a, Integral a, Generic a, Rep a ~ D1 d f, Datatype d) => SchemaOptions -> Proxy a -> NamedSchema Source #

Default generic named schema for Bounded, Integral types.

genericDeclareNamedSchemaNewtype Source #

Arguments

:: forall a d c s i inner. (Generic a, Datatype d, Rep a ~ D1 d (C1 c (S1 s (K1 i inner)))) 
=> SchemaOptions

How to derive the name.

-> (Proxy inner -> Declare (Definitions Schema) Schema)

How to create a schema for the wrapped type.

-> Proxy a 
-> Declare (Definitions Schema) NamedSchema 

Declare a named schema for a newtype wrapper.

declareSchemaBoundedEnumKeyMapping :: forall map key value. (Bounded key, Enum key, ToJSONKey key, ToSchema key, ToSchema value) => Proxy (map key value) -> Declare (Definitions Schema) Schema Source #

Declare Schema for a mapping with Bounded Enum keys. This makes a much more useful schema when there aren't many options for key values.

>>> data ButtonState = Neutral | Focus | Active | Hover | Disabled deriving (Show, Bounded, Enum, Generic)
>>> instance ToJSON ButtonState
>>> instance ToSchema ButtonState
>>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show)
>>> type ImageUrl = T.Text
>>> BSL.putStrLn $ encodePretty $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))
{
    "properties": {
        "Active": {
            "type": "string"
        },
        "Disabled": {
            "type": "string"
        },
        "Focus": {
            "type": "string"
        },
        "Hover": {
            "type": "string"
        },
        "Neutral": {
            "type": "string"
        }
    },
    "type": "object"
}

Note: this is only useful when key is encoded with ToJSONKeyText. If it is encoded with ToJSONKeyValue then a regular schema for [(key, value)] is used.

toSchemaBoundedEnumKeyMapping :: forall map key value. (Bounded key, Enum key, ToJSONKey key, ToSchema key, ToSchema value) => Proxy (map key value) -> Schema Source #

A Schema for a mapping with Bounded Enum keys. This makes a much more useful schema when there aren't many options for key values.

>>> data ButtonState = Neutral | Focus | Active | Hover | Disabled deriving (Show, Bounded, Enum, Generic)
>>> instance ToJSON ButtonState
>>> instance ToSchema ButtonState
>>> instance ToJSONKey ButtonState where toJSONKey = toJSONKeyText (T.pack . show)
>>> type ImageUrl = T.Text
>>> BSL.putStrLn $ encodePretty $ toSchemaBoundedEnumKeyMapping (Proxy :: Proxy (Map ButtonState ImageUrl))
{
    "properties": {
        "Active": {
            "type": "string"
        },
        "Disabled": {
            "type": "string"
        },
        "Focus": {
            "type": "string"
        },
        "Hover": {
            "type": "string"
        },
        "Neutral": {
            "type": "string"
        }
    },
    "type": "object"
}

Note: this is only useful when key is encoded with ToJSONKeyText. If it is encoded with ToJSONKeyValue then a regular schema for [(key, value)] is used.

genericDeclareSchema :: (Generic a, GToSchema (Rep a), Typeable a) => SchemaOptions -> Proxy a -> Declare (Definitions Schema) Schema Source #

A configurable generic Schema creator.

genericDeclareNamedSchema :: forall a. (Generic a, GToSchema (Rep a), Typeable a) => SchemaOptions -> Proxy a -> Declare (Definitions Schema) NamedSchema Source #

A configurable generic NamedSchema creator. This function applied to defaultSchemaOptions is used as the default for declareNamedSchema when the type is an instance of Generic.

Default implementation will use the name from Typeable instance, including concrete instantioations of type variables.

For example:

>>> _namedSchemaName $ undeclare $ genericDeclareNamedSchema defaultSchemaOptions (Proxy :: Proxy (Either Int Bool))
Just "Either_Int_Bool"

genericNameSchema :: forall a d f. (Generic a, Rep a ~ D1 d f, Datatype d) => SchemaOptions -> Proxy a -> Schema -> NamedSchema Source #

Derive a Generic-based name for a datatype and assign it to a given Schema.

withFieldSchema :: forall proxy s f. (Selector s, GToSchema f) => SchemaOptions -> proxy s f -> Bool -> Schema -> Declare (Definitions Schema) Schema Source #

gsumConToSchemaWith :: forall c f. (GToSchema (C1 c f), Constructor c) => Maybe (Referenced Schema) -> SchemaOptions -> Proxy (C1 c f) -> (Text, Referenced Schema) Source #

Convert one component of the sum to schema, to be later combined with oneOf.

data Proxy2 a b Source #

Constructors

Proxy2 

data Proxy3 a b c Source #

Constructors

Proxy3 
>>> import Data.OpenApi
>>> import Data.Aeson (encode)
>>> import Data.Aeson.Types (toJSONKeyText)
>>> import Data.OpenApi.Internal.Utils
>>> :set -XScopedTypeVariables
>>> :set -XDeriveAnyClass
>>> :set -XStandaloneDeriving
>>> :set -XTypeApplications