2015-02-13 6 views
2

У меня есть тип Foo a и хочу тип EnumFoo a который требует instance Enum (Foo a). Как вы объявляете этот тип?Предпосылки для типов?

Допустим, мы объявляем Foo как это:

type Foo a = Maybe a 

Там может быть Foo Int, Foo String и ничего.
Теперь я объявляю экземпляр Enum на Foo Int:

instance Enum (Foo Int) where 
    ... 

Там могут быть некоторые другие Foo, что есть экземпляр Enum, как это. Назовем эти типы EnumFoo a. Как вы это выражаете?

Это не работает, но то, что я хотел бы сделать:

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

Я не уверен, что это называется, так что название не должно делать никакого смысла.

+2

Это почти разумно, но не совсем. Можете ли вы попытаться объяснить немного больше, что вам нужно? Если вы можете дать немного контекста, это очень поможет. – dfeuer

+1

@dfeuer Я просто добавил еще несколько. Имеет ли это смысл? –

+1

Я вижу две интерпретации: (a) 'EnumFoo' пытается захватить коллекцию типов, которые являются« Foo a »такими, что есть экземпляр« Enum (Foo a) ». Или (b) 'EnumFoo a' - это« функция типа », которая разрешает« Foo a »всякий раз, когда есть экземпляр« Enum (Foo a) ». Являются ли они такими близкими? Что-то другое? – luqui

ответ

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 a (кроме undefined) заключается в применении EnumFoo конструктор, который налагают Enum (Foo a) контекст. Вы можете написать такие вещи, как

blah :: EnumFoo a -> [EnumFoo a] 
blah (EnumFoo foo) = map EnumFoo [toEnum 1 .. foo] 

Обратите внимание, что вам нужно расширение FlexibleContexts, потому что стандарт Haskell не позволяет контекст как Enum (Foo a); он позволяет только простые вещи, такие как Enum Foo или Enum a.

bheklilr также упомянул старую форму декларации, введя контекст в стандартную декларацию data. Хотя эта форма является стандартным Haskell (это в отчетах Haskell 98 и Haskell 2010), она настолько широко считается ошибочной, что GHC даже не разрешает ее без прагмы LANGUAGE. Проблема заключается в том, что, хотя она ограничивает допустимость переменных типа, она не позволяет использовать эти ограничения.

+0

Спасибо за ваш ответ, но есть ли какие-либо методы для перевода экземпляра на объект? Или я должен задать другой вопрос: –

+0

@ RyoichiroOka, я не понимаю, что вы имеете в виду. – dfeuer

Смежные вопросы