类型的先决条件?

Ryo*_*Oka 2 haskell

我有一个类型Foo a,想要一个EnumFoo a需要的类型instance Enum (Foo a).你怎么声明这种类型?

假设我们这样声明Foo:

type Foo a = Maybe a
Run Code Online (Sandbox Code Playgroud)

可以有Foo Int,有Foo String什么.
现在我声明一个Enumon 的实例Foo Int:

instance Enum (Foo Int) where
  ...
Run Code Online (Sandbox Code Playgroud)

可能还有其他Foo一些具有这样的实例Enum.我们称之为那些类型EnumFoo a.你是怎么表达的?

这不起作用,但我想做的是:

type (Enum (Foo a)) => EnumFoo a = Foo a
Run Code Online (Sandbox Code Playgroud)

我不确定它叫什么,所以标题应该毫无意义.

dfe*_*uer 6

正如bheklilr 所说,听起来你想要的是一个GADT:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
module Foo where

data Foo a = Foo (Maybe a)

data EnumFoo a where
  EnumFoo :: Enum (Foo a) => Foo a -> EnumFoo a
Run Code Online (Sandbox Code Playgroud)

制作EnumFoo a(除了undefined)之外的唯一方法是应用EnumFoo构造函数,它构造了一个Enum (Foo a)上下文.然后你可以写出类似的东西

blah :: EnumFoo a -> [EnumFoo a]
blah (EnumFoo foo) = map EnumFoo [toEnum 1 .. foo]
Run Code Online (Sandbox Code Playgroud)

请注意,您需要FlexibleContexts扩展名,因为标准Haskell不允许上下文Enum (Foo a); 它只允许简单的事情,如Enum FooEnum a.

bheklilr还提到了一个较旧的声明表,在标准data声明中加上了背景.虽然这种形式是标准的Haskell(它在Haskell 98和Haskell 2010报告中),但它被广泛认为是错误的,GHC甚至不允许没有LANGUAGE编译指示.问题在于虽然它限制了允许的类型变量,但它不允许您使用这些约束.