() 作为空约束
() as empty constraint
如何表示空约束?
对于以下文件
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE KindSignatures #-}
import Data.Kind(Type, Constraint)
type Empty = (() :: Type -> Constraint)
main :: IO ()
main = return ()
ghc 8.2.2 答案
constraint.hs:6:15: error:
• Expected kind ‘* -> Constraint’, but ‘()’ has kind ‘*’
• In the type ‘(() :: Type -> Constraint)’
In the type declaration for ‘Empty’
|
6 | type Empty = (() :: Type -> Constraint)
|
我想念什么?
我知道以下解决方案
{-# LANGUAGE FlexibleInstances #-}
class Empty x
instance Empty x
但我想知道为什么 () 不起作用
()
具有种类 Constraint
,并不意味着应用于 Type
.
()
has kind *
or Constraint
, depending on context, never a -> Constraint
. Similarly (,)
has kind * -> * -> *
or Constraint -> Constraint -> Constraint
, depending on context.
只是()
只是重载了无论是类型还是约束。也就是说,你会写 () => a
,而不是 (() a) => a
。所以我认为:
class Empty x
instance Empty x
这里是正确的解决方案。 (也许类似的东西应该在 base
中。)
根据您的需要,这些都可以正常工作:
type Empty = (() :: Constraint)
type ConstEmpty x = (() :: Constraint)
是正确的。如果你想要一件事你可以不管 arity(实例头或类型族 LHS 除外),你将需要使用一些样板:
{-# language PolyKinds, ConstraintKinds, FlexibleInstances,
MultiParamTypeClasses, TypeFamilies #-}
import Data.Kind (Constraint)
class Unit1 a
instance Unit1 a
class Unit2 a b
instance Unit2 a b
...
type family Unit :: k
type instance Unit = (() :: Constraint)
type instance Unit = Unit1
type instance Unit = Unit2
...
然后
Prelude K> type Empty = (Unit :: Type -> Constraint)
Prelude K> :kind! Empty
Empty :: * -> Constraint
= Unit1
如何表示空约束?
对于以下文件
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE KindSignatures #-}
import Data.Kind(Type, Constraint)
type Empty = (() :: Type -> Constraint)
main :: IO ()
main = return ()
ghc 8.2.2 答案
constraint.hs:6:15: error:
• Expected kind ‘* -> Constraint’, but ‘()’ has kind ‘*’
• In the type ‘(() :: Type -> Constraint)’
In the type declaration for ‘Empty’
|
6 | type Empty = (() :: Type -> Constraint)
|
我想念什么?
我知道以下解决方案
{-# LANGUAGE FlexibleInstances #-}
class Empty x
instance Empty x
但我想知道为什么 () 不起作用
()
具有种类 Constraint
,并不意味着应用于 Type
.
()
has kind*
orConstraint
, depending on context, nevera -> Constraint
. Similarly(,)
has kind* -> * -> *
orConstraint -> Constraint -> Constraint
, depending on context.
只是()
只是重载了无论是类型还是约束。也就是说,你会写 () => a
,而不是 (() a) => a
。所以我认为:
class Empty x
instance Empty x
这里是正确的解决方案。 (也许类似的东西应该在 base
中。)
根据您的需要,这些都可以正常工作:
type Empty = (() :: Constraint)
type ConstEmpty x = (() :: Constraint)
{-# language PolyKinds, ConstraintKinds, FlexibleInstances,
MultiParamTypeClasses, TypeFamilies #-}
import Data.Kind (Constraint)
class Unit1 a
instance Unit1 a
class Unit2 a b
instance Unit2 a b
...
type family Unit :: k
type instance Unit = (() :: Constraint)
type instance Unit = Unit1
type instance Unit = Unit2
...
然后
Prelude K> type Empty = (Unit :: Type -> Constraint)
Prelude K> :kind! Empty
Empty :: * -> Constraint
= Unit1