2013-10-05 6 views
1

This question показывает определение экземпляра для (,) a b, где a является экземпляром Monoid.Экземпляр Monad для пар

Однако, я не знаю, как написать аналогичную вещь для (,) a b, а b - это пример Monoid? Я могу в принципе сделать это до тех пор, как я могу написать определение:

instance Monoid b => Monad ((,) ???) where 
    return a = (a,mempty) 
    ~(a,b) >>= f = let (c,b1) in f a in (c,b `mappend` b1) 

Таким образом, вопрос, как написать ??? часть?

UPDATE

На самом деле этот вопрос частный случай более общей проблемы: можно ли написать экземпляр класса типа, которые действуют на некоторых типах, которые не появляются в конце? В моем случае конструктор типа имеет значение (,) a b, и я хочу сделать его экземпляром Monad a, где a не является последним параметром типа.

ответ

5

Мы могли бы написать, потому что теперь синонимы работает неприемлемым для этого случая, так что мы используем Newtype:

newtype RevTuple b a = RevTuple { totuple :: (a , b) } 

instance Monoid b => Monad (RevTuple b) where 
    return a = RevTuple (a,mempty) 
    (RevTuple (a,b)) >>= f = 
       let RevTuple (c,b1) = f a in RevTuple (c,b `mappend` b1) 
+0

Это не очень хорошо, так как каждый раз, когда я хочу использовать 'RevTuple', я должен использовать конструктор типов и' totuple'. –

+0

@ EarthEngine Hope, позже мы могли бы использовать типы: 'type RevTuple b a = (a, b)' в этой ситуации – wit

+0

У вас может быть такое определение уже. Проблема в том, что вы не можете сказать «экземпляр Monoid b => Monad (RevTuple b)» в этом случае. –

1

Вы не можете. Крайне важно, чтобы Monad был полиморфным по своему параметру, поэтому, если конкретная монадическая вещь имеет смысл только для моноидов, это не монада.

Например, return :: Monad m => a -> m a. Нет никакого способа добавить дополнительное ограничение к сигнатуре return.

+0

Пожалуйста, обратитесь к моему обновлению. Дело в том, что я хочу заставить экземпляр «Monad» действовать на 'a' of' (,) a b', а не 'b'. –

+1

Это во всех смыслах эквивалентно существующему экземпляру «Монада», только с переворотом заказа. Есть ли причина, по которой вы не можете использовать существующий экземпляр и перевернуть заказ продукта, когда вам это нужно наоборот? – kqr

+0

@kqr Обычно вы можете перевернуть заказ перед использованием. Однако я просто хочу знать, в общем, могу ли я это сделать? Как я могу это сделать? Я нашел некоторые другие случаи, что это может быть полезно. Кроме того, я думаю, что повторный вызов 'flip' все еще повторяется. –

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