You can think of structural record types as being formed by applying a special type constructor to a type-level collection of types:
row Fields = [name: String, age: Int]
type Person = MkRecord Fields
Which have kinds:
MkRecord :: Row Type -> Type
Fields :: Row Type
Person :: Type
You can construct variant types in a similar way:
row Cases = [success: SyntaxTree, failure: ParseError]
type ParseResult = MkVariant Cases
Which have kinds:
MkVariant :: Row Type -> Type
Cases :: Row Type
ParseResult :: Type
Rows may contain things other than proper types, for example:
row Effects = [foo: State s, bar: Except e]
type Action = MkFunction Effects
Which have kind:
-- function types now take three arguments:
-- - row of effects
-- - argument type
-- - return type
MkFunction :: Row Effect -> Type -> Type -> Type
Effects :: Row Effect
Action :: Type -> Type -> Type