2016-03-16 2 views
1

классов типов Для этих данных:Haskell: Преобразование между

data A = A 
data B = B 

class C1 a where repr :: a -> String 
instance C1 A where repr _ = "A" 
instance C1 B where repr _ = "B" 

class C2 a 
instance C2 A 

Есть ли способ, чтобы реализовать функцию с этим типом?

conv :: (C1 a, C2 b) => a -> Maybe b 

Она должна возвращать Just . id для аргумента типа, который является экземпляром C2 и Nothing для любого другого типа.

repr является инъективным. Я могу изменить класс C2, но класс C1 находится в внешней библиотеке.

+5

Пожалуйста, будьте более конкретными. Не упрощайте проблему. Как и в настоящее время, этот вопрос представляется экземпляром проблемы [XY] (http://xyproblem.info/). –

+0

Я не вижу никакого упрощения. Пример довольно конкретный, и вопрос в основном да/нет. Если это невозможно сделать, что мне нужно, ответьте, что это не так, и я буду благодарен, если вы объясните, почему. –

+4

Проблема с вашим вопросом заключается в том, что вы спрашиваете о своем __attempted решении__ вместо вашей __actual problem__. У вас есть проблема, для которой вы хотите получить решение, и вы уже подумали о решении (в вашем случае реализации функции conv). Следовательно, вы спрашиваете, можно ли реализовать функцию conv. Однако, если вы сообщите нам свою реальную проблему (ту, которую вы пытаетесь решить, реализуя функцию conv), мы можем дать вам лучший ответ. Следовательно, это упрощение проблемы __actual__, которую вы имеете. Просто пытаюсь помочь здесь бесплатно. –

ответ

6

Нет, это невозможно. В предположении открытого мира говорится, что нет способа показать (во время компиляции или во время выполнения), что данный тип не экземпляр данного класса.

+0

Хороший ответ. Но возникает другой вопрос: что, если мы точно знаем типы, которые принадлежат «C2»? Мы можем сопоставить результаты 'repr' с этими типами, но возможно ли вообще вернуть' a -> Может быть, '... http://stackoverflow.com/questions/36033698/haskell-filtering-by-type –

2

Зачем нужен класс типа C2? Вы можете просто сделать это:

conv :: C1 a => a -> Maybe a 
conv a = case repr a of 
      "A" -> Just a 
      _ -> Nothing 

Это работает в предположении, что функция repr является injective.


Edit: Вот как реализовать функцию conv так, как вы хотите:

{-# LANGUAGE TypeFamilies #-} 

conv :: (C1 a, C2 b, a ~ b) => a -> Maybe b 
conv a = case repr a of 
      "A" -> Just a 
      _ -> Nothing 

Обратите внимание, что ограничение равенства a ~ b требуется. Он сообщает компилятору, что тип a и тип b должны быть одного типа. Чтобы использовать ограничение равенства, нам нужно включить расширение TypeFamilies.

+0

Существует много примеров классов «C2» (сотни) и «C2», на самом деле имеет несколько методов.Используя это решение (без класса вообще), нам нужно было бы создать несколько различных больших функций, похожих на 'conv', каждый из которых будет в основном перечислять все имена типов, которые будут экземплярами' C2'. Кроме того, мы хотим обеспечить, чтобы для каждого типа, являющегося экземпляром «C2», были реализованы все методы. Опять же, это будет сложно с помощью отдельных функций ... –

+0

Зачем вам нужно создавать несколько функций, похожих на 'conv'? Только один будет делать, что он будет довольно большой функцией, если у вас есть сотни экземпляров 'C2'. –

+1

Обеспечение того, что все методы экземпляра класса типа реализованы, - это работа компилятора. Ваш вопрос ужасно упрощен. Я не знаю, что вы пытаетесь сделать. Пожалуйста, будьте более конкретными. Кажется, это проблема [XY] (http://xyproblem.info/). –

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