2014-01-13 3 views
0

Чтобы лучше понять монады, я пытаюсь написать свои собственные. Я начинаю с некоторого не монадического кода и могу использовать некоторую помощь, переводя его в монаду.Haskell: перевод на Monad

Основная идея этого надуманного примера: для каждого целочисленного результата вычисления я хотел бы отслеживать, является ли это целое четным или нечетным. Например, в 4 + 5 = 9 мы можем вернуть (9, Odd).

Я хотел бы иметь возможность связывать/составлять вычисления с помощью >>=. Например:

return 1 >>= (+2) >>= (+5) >>= (+7) =result=> (15, Odd) 

Прямо сейчас, у меня есть следующий, не монадический код:

data Quality = Odd | Even deriving Show 

qual :: Integer -> Quality 
qual x = case odd x of 
      True -> Odd 
      _ -> Even 

type Qualifier = (Integer, Quality) 

mkQ :: Integer -> Qualifier 
mkQ x = (x, qual x) 

plusQ :: Qualifier -> Qualifier -> Qualifier 
plusQ (x, _) (y, _) = (x+y, qual (x+y)) 

chain = plusQ (mkQ 7) . plusQ (mkQ 5) . plusQ (mkQ 2) 

Какие способами я могу перевести приведенный выше код в монады? Каковы некоторые из шаблонов, которые я должен искать, и каковы общие шаблоны переводов для них?

Большое спасибо заранее!

+2

Это не легко допускает монадический перевод. Монады параметризуются типом и имеют смысл для любого типа. Вычисление Yor имеет смысл только для intrgers. –

+1

Кажется, вы пытаетесь моделировать преобразования/действия состояния, где ваше состояние в этом случае является «качеством». Вы захотите посмотреть на [** State Monad **] (http://learnyouahaskell.com/for-a-few-monads-more), где ваша государственная монада параметризуется с помощью 'Quality' и ваших операций' (+1) 'превратится в действия государства. – aaronlevin

+0

@ н.м.Хороший момент, и тот, о котором я начинал видеть и удивляться. Что может быть лучшим примером простого, общего процесса, который бы соответствовал этому упражнению? –

ответ

0

Много уроков из этого. Большое спасибо комментаторам и ответам за ваше время и руководство!

Резюмируя:

Решение: Как @ N.m. и другие прокомментировали, для этого примера нет хорошего перевода монады, потому что моя оригинальная модель не является типичной. Монады лучше всего подходят для типовых вычислений. Приведенные хорошие примеры включают в себя монаду Maybe для вычислений, которые могут потерпеть неудачу, и монашеская монада для хранения и переноса информации о вспомогательных состояниях через цепочку вычислений.

В качестве альтернативное решение, @GabrielGonzalez предлагает отличное решение с использованием типа instancing. Это сохраняет присущую спецификацию по типу моей исходной модели, но расширяет ее интерфейс для поддержки большего количества интерфейса класса Num и очистки функциональных взаимодействий.

Следующие шаги: В соответствии с рекомендациями @weirdcanada и другие, я думаю, что я пойду играть с State монады и посмотреть, как я могу применить его к этому конкретному примеру. Затем я могу попробовать свои силы в пользовательском определении Maybe как @ n.m. рекомендуемые.

Снова большое спасибо тем, кто прокомментировал и ответил!

3

Я думаю, что вы на самом деле хотите это Num экземпляр для Qualified:

data Qualified = Qualified { isEven :: Bool, value :: Integer } 

instance Num Qualified where 
    (Qualified e1 n1) + (Qualified e2 n2) = Qualified e (n1 + n2) 
     where 
     e = (e1 && e2) || (not e1 && not e2) 

    (Qualified e1 n1) * (Qualified e2 n2) = Qualified (e1 || e2) (n1 * n2) 

    abs (Qualified e n) = Qualified e (abs n) 

    signum (Qualified e n) = Qualified e (signum n) 

    fromInteger n = Qualified (even n) n 

Это позволяет манипулировать Qualified номера, используя математические операторы:

>>> let a = fromInteger 3 :: Qualified 
>>> let b = fromInteger 4 :: Qualified 
>>> a 
Qualified {isEven = False, value = 3} 
>>> b 
Qualified {isEven = True, value = 4} 
>>> a + b 
Qualified {isEven = False, value = 7} 
>>> a * b 
Qualified {isEven = True, value = 12} 
+1

OP вероятно хочет экземпляр «Num», но я думаю, что более широкая цель состоит в том, что OP хочет учиться и понимать монады. – aaronlevin

+3

Я волнуюсь, что преподавание монадов в контексте этой конкретной проблемы принесет больше вреда, чем пользы. –

+0

@GabrielGonzalez хорошая забота, и беспокойство признано. Что может быть лучшим простым монадом, который можно написать с нуля, чтобы лучше понять монады? –

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