{- |
    Module      :  $Header$
    Description :  Internal representation of kinds
    Copyright   :  (c) 2016        Finn Teegen
    License     :  BSD-3-clause

    Maintainer  :  bjp@informatik.uni-kiel.de
    Stability   :  experimental
    Portability :  portable

   This module modules provides the definitions for the internal
   representation of kinds in the compiler.
-}

module Base.Kinds where

-- A kind is either *, which is the kind of a value's type, a kind
-- variable, or an arrow kind. Kind variables are used internally during
-- kind inference. Kind variables are not supported in Curry kind
-- expressions and all kind variables that remain free after kind
-- inference are instantiated to *.

data Kind = KindStar
          | KindVariable Int
          | KindArrow Kind Kind
  deriving (Kind -> Kind -> Bool
(Kind -> Kind -> Bool) -> (Kind -> Kind -> Bool) -> Eq Kind
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Kind -> Kind -> Bool
$c/= :: Kind -> Kind -> Bool
== :: Kind -> Kind -> Bool
$c== :: Kind -> Kind -> Bool
Eq, Int -> Kind -> ShowS
[Kind] -> ShowS
Kind -> String
(Int -> Kind -> ShowS)
-> (Kind -> String) -> ([Kind] -> ShowS) -> Show Kind
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Kind] -> ShowS
$cshowList :: [Kind] -> ShowS
show :: Kind -> String
$cshow :: Kind -> String
showsPrec :: Int -> Kind -> ShowS
$cshowsPrec :: Int -> Kind -> ShowS
Show)

-- |The function 'kindArity' computes the arity n of a kind.
kindArity :: Kind -> Int
kindArity :: Kind -> Int
kindArity (KindArrow _ k :: Kind
k) = 1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Kind -> Int
kindArity Kind
k
kindArity _               = 0

-- |The function 'kindVars' returns a list of all kind variables
-- occurring in a kind.
kindVars :: Kind -> [Int]
kindVars :: Kind -> [Int]
kindVars k :: Kind
k = Kind -> [Int] -> [Int]
vars Kind
k []
  where
    vars :: Kind -> [Int] -> [Int]
vars KindStar          kvs :: [Int]
kvs = [Int]
kvs
    vars (KindVariable kv :: Int
kv) kvs :: [Int]
kvs = Int
kv Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
kvs
    vars (KindArrow k1 :: Kind
k1 k2 :: Kind
k2) kvs :: [Int]
kvs = Kind -> [Int] -> [Int]
vars Kind
k1 ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ Kind -> [Int] -> [Int]
vars Kind
k2 [Int]
kvs

-- |The function 'defaultKind' instantiates all kind variables
-- occurring in a kind to *.
defaultKind :: Kind -> Kind
defaultKind :: Kind -> Kind
defaultKind (KindArrow k1 :: Kind
k1 k2 :: Kind
k2) = Kind -> Kind -> Kind
KindArrow (Kind -> Kind
defaultKind Kind
k1) (Kind -> Kind
defaultKind Kind
k2)
defaultKind _                 = Kind
KindStar

-- |The function 'simpleKind' returns the kind of a type
-- constructor with arity n whose arguments all have kind *.
simpleKind :: Int -> Kind
simpleKind :: Int -> Kind
simpleKind n :: Int
n = (Kind -> Kind -> Kind) -> Kind -> [Kind] -> Kind
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Kind -> Kind -> Kind
KindArrow Kind
KindStar ([Kind] -> Kind) -> [Kind] -> Kind
forall a b. (a -> b) -> a -> b
$ Int -> Kind -> [Kind]
forall a. Int -> a -> [a]
replicate Int
n Kind
KindStar

-- |The function 'isSimpleKind' returns whether a kind is simple or not.
isSimpleKind :: Kind -> Bool
isSimpleKind :: Kind -> Bool
isSimpleKind k :: Kind
k = Kind
k Kind -> Kind -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Kind
simpleKind (Kind -> Int
kindArity Kind
k)