ищите учебное упражнение: реализуйте эти монады - PullRequest
7 голосов
/ 03 октября 2009

При изучении новых предметов программирования я обычно следую шаблону: я читаю об этом, понимаю его, а затем кодирую несколько примеров, чтобы убедиться, что действительно понял .

Я много читал о монадах, и я уверен, что понимаю и понимаю их. Сейчас я нахожусь на этапе, когда мне действительно хотелось бы написать несколько монад, чтобы укрепить мое понимание, и действительно выяснить, что нужно для реализации bind для различных типов.

Проблема в том, что я не могу придумать много очевидных монад для реализации, поэтому я ищу рекомендации. Желательно, чтобы я хотел список рекомендаций, с некоторыми простыми, а некоторые не такими легкими.

Я также понимаю, что хотя монады используются для «инкапсуляции» побочных эффектов в функциональных программах, они также носят более общий характер. Итак, я хотел бы, чтобы в рекомендации были включены монады, которые как инкапсулируют побочные эффекты, так и некоторые общие.

Спасибо!

(как примечание: я буду работать с f #, чтобы сделать это, но я думаю, что этот вопрос может относиться к любому функциональному языку).

Ответы [ 3 ]

5 голосов
/ 04 октября 2009

Я думаю, что каталог в All About Monads - хорошее начало (монада продолжения действительно полезна для катаморфизмов, см., Например, здесь ); дополнительно парсеры и, возможно, транзакционные эффекты . Async - еще один хороший вариант, который можно попробовать реализовать самостоятельно (логически однопоточный код, который переходит через разные фактические потоки, чтобы быть неблокирующим). А базовая монада Reactive Framework выглядит как хорошая сложная задача.

2 голосов
/ 03 октября 2009

Список структур данных / вычислений, которые следуют некоторому монадическому закону, чрезвычайно богат.

Он достигает от списков дополнительных данных ('a option в F #), продолжений и многопоточности, вплоть до очень сложных вещей, таких как парсеры.

Просто начните реализовывать некоторые из них. Основные занятия:

// Identity monad

let something = ident {
    let! value = id 42
    return value
}

let somethingelse = ident {
    let! value = something
    let! otherValues = id 40
    return value + othervalue
}


// Implement maybe for 'a option
let sum = maybe {
    let! a = maybeInputNumber("a")
    let! b = maybeInputNumber("b")
    let! c = maybeInputNumber("c")
    return a + b + c
}

match sum with
| None -> ...
| Some(n) -> ...

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

// Given m >>= f for m.Bind(f)

let (>-) f monad = monad >>= (fun k -> return(f x))

// What's this?
let res = ((+) 1) >- [1..10]

Если вам нужны сложные примеры, взгляните на комбинаторы монадических парсеров . Это позволит вам реализовать сложные парсеры рекурсивного спуска на простом F # (взгляните на FParsec -Project)

let parseVector = parser {
    do! ignore $ char '('
    let! [x;y;z] = sepBy parseNumber "," 
    do! ignore $ char ')'
    return new Vector(x, y, z)
}

Простая реализация для этого основана на следующих типах:

type 't Computation = 
    | Error of ...
    | Result of 't

type Input     = char list
type 'a Parser = Input -> (('a * Input) Computation)

Попробуйте реализовать bind и return ; -)

И в качестве общего совета: если вы действительно хотите понять монады в их естественной среде, вам придется использовать Haskell ;-) В F # есть только выражения для вычислений, просто расплывчатый аналог, но Haskell вводит общий интерфейс для любого монадического вычисления. Идеально, чтобы попробовать их!

1 голос
/ 19 декабря 2009

Хотя я полагаю, что нет сомнений в том, что Haskell является естественным языком для изучения монад, я считаю, что очень полезным упражнением является приведение монадических вычислений к языку, в котором нет стандартного языка Haskell. как супер гладкая поддержка для них. Это вполне возможно на любом языке, и на любом языке достаточно высокого уровня, возможно, удастся проявить креативность и действительно заставить их выглядеть красиво - многому научиться в процессе! Я видел классный монадический синтаксис для Python (например, Valued Lessons ).

Есть также библиотека Clojure.contrib.monads, которая предоставляет удобные средства для использования монад в Лиспе. Попытка воссоздать некоторые из его функций может быть весьма поучительной. Кроме того, использование его иногда вместо Haskell может быть полезным для отделения общих шаблонов от особенностей синтаксиса Haskell (хотя они, конечно, весьма хороши).

...