类型的先决条件?

时间:2015-02-13 05:04:35

标签: haskell

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

假设我们像这样声明Foo

type Foo a = Maybe a

可以有Foo IntFoo String等任何内容 现在我在Enum上声明Foo Int的实例:

instance Enum (Foo Int) where
  ...

可能有一些其他Foo具有Enum这样的实例。我们称这些类型为EnumFoo a。你是如何表达的?

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

type (Enum (Foo a)) => EnumFoo a = Foo a

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

1 个答案:

答案 0 :(得分:6)

作为bheklilr suggested,听起来你想要的是一个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

制作EnumFoo aundefined除外)的唯一方法是应用EnumFoo构造函数,该构造函数强加Enum (Foo a)上下文。然后你可以写一些像

这样的东西
blah :: EnumFoo a -> [EnumFoo a]
blah (EnumFoo foo) = map EnumFoo [toEnum 1 .. foo]

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

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