() как пустое ограничение

Как можно представить пустое ограничение?

для следующего файла

{-# 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 ответа

Решение

() имеет вид * или же Constraintв зависимости от контекста, никогда a -> Constraint, так же (,) имеет вид * -> * -> * или же Constraint -> Constraint -> Constraintв зависимости от контекста.

- Саймон Пейтон-Джонс

Это просто () перегружается только для типа или ограничения. То есть ты бы написал () => aне (() a) => a, Так что я думаю это:

class Empty x
instance Empty x

Это правильное решение здесь. (И, возможно, что-то подобное должно быть в base.)

Ответ Джона Перди правильный. Если вам нужна одна вещь, которую вы можете использовать независимо от арности (за исключением главы экземпляра или семейства типов 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

() имеет вид Constraint и не предназначен для применения к Type,

Любой из них работает нормально, в зависимости от того, что вы хотите:

type Empty = (() :: Constraint)
type ConstEmpty x = (() :: Constraint)
Другие вопросы по тегам