2013-02-14 3 views
2

мне нужно объявить экземпляр Monad для конкретного типа данных:шаблона на объявлении экземпляра

data M m a = Mk (m (Maybe a)) 

instance (Monad m) => Monad (M m) where 
    return x = Mk (m (Just x)) 
    Mk (m (Nothing)) >>= f = Mk (m (Nothing)) 
    Mk (m (Just x)) >>= f = f x 

Но я получаю:

test.hs:6:7: Parse error in pattern: m 
Failed, modules loaded: none. 

Это может быть очень простым, но я не могу понять это из!

ответ

5

Тип переменной m - это не то, на что вы можете сопоставить рисунок, особенно для того, чтобы отличать Just и Nothing. Подумайте, что это означало бы для разных возможных типов, используемых вместо m - во многих случаях такое совпадение шаблонов было бы совершенно невозможно.

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

instance (Monad m) => Monad (M m) where 
    return x = Mk (return (Just x)) 
    Mk mx >>= f = -- ?? 

return Обратите внимание на используемый для создания значения типа m (Maybe a) --that возможно из-за Monad m ограничения, и в общем случае (без каких-либо ограничений) не было бы способа создать такое значение.

Для реализации (>>=) вам нужно сделать что-то подобное, также используя (>>=) для Monad экземпляра m.

Кстати, вам стоит подумать о том, чтобы использовать newtype для M, если у вас нет определенной причины для получения data. В большинстве случаев, если вы можете использовать newtype, вам нужно.

0

Вы можете сопоставлять шаблон только по конструктору, а не по другому. Вам нужно будет использовать экземпляр Monad для m, чтобы добраться до данных Maybe, которые находятся внутри. Я не уверен на 100%, что у этого есть поведение, которое вы хотите, но оно имеет тип typecheck.

data M m a = Mk (m (Maybe a)) 

instance (Monad m) => Monad (M m) where 
    return x = Mk (return (Just x)) 
    Mk m >>= f = Mk (m >>= go) 
    where go (Just x) = let Mk x' = f x in x' 
      go _  = return Nothing 
+0

Thnaks вы оба! Теперь я понял, что я делаю неправильно! – nicoan

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