代码之家  ›  专栏  ›  技术社区  ›  libeako

()作为空约束

  •  3
  • libeako  · 技术社区  · 6 年前

    如何表示空约束?

    对于以下文件

    {-# 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
    

    但我想知道为什么()不起作用

    4 回复  |  直到 6 年前
        1
  •  5
  •   Community CDub    4 年前

    () 有种 * Constraint ,取决于上下文,从不 a -> Constraint .类似地 (,) 有种 * -> * -> * Constraint -> Constraint -> Constraint ,具体取决于上下文。

    –俬 Simon Peyton-Jones

    就是这样 () 仅针对其是类型还是约束重载。也就是说,你会写 () => a (() a) => a .所以我认为:

    class Empty x
    instance Empty x
    

    是这里的正确解决方案。(也许应该是这样的 base .)

        2
  •  3
  •   Li-yao Xia    6 年前

    () 有种 Constraint 不适用于 Type

        3
  •  3
  •   dfeuer    6 年前

    Jon Purdy's answer 是正确的。如果您想要一件无论arity如何都可以插入的东西(除了在实例head或type family 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
    
        4
  •  0
  •   Daniel Wagner    6 年前

    根据您的需要,这两种方法都很好:

    type Empty = (() :: Constraint)
    type ConstEmpty x = (() :: Constraint)
    
    推荐文章