Как реализовать «функциональные» монады в ракетке, используя функционал data / monad module? - PullRequest
0 голосов
/ 13 сентября 2018

Поскольку нотация do модуля data / monad работает со структурами, как я могу определить типы монад, которые являются функциями, например парсерами?

Я привык к OCaml, где моя монада имела бы примерноследующая подпись:

module type Parser = sig
  type state = string * int
  type 'a t = state -> (('a * state), string) Result.t

  val return: 'a -> 'a t
  val bind: 'a t -> ('a -> 'b t) -> 'b t
end

Извините, что опубликовал пример в OCaml, мои возможности в области ракеток пока невелики.

Совместим ли этот тип монады с данными / монадой илия должен смотреть на другое решение?

1 Ответ

0 голосов
/ 13 сентября 2018

Ничто не мешает вам обернуть функцию в структуру, а затем реализовать интерфейс gen:monad в этой структуре. Библиотека мегапарсаков - пример, использующий эту технику для реализации библиотеки монадического синтаксического анализатора.В частности, взгляните на определение parser структуры :

(struct parser (proc)
  #:methods gen:functor
  [(define/generic -map map)
   (define (map f p)
     (parser (compose (match-lambda [(consumed (ok v rest message)) (consumed (ok (-map f v) rest message))]
                                    [(empty (ok v rest message))    (empty (ok (-map f v) rest message))]
                                    [error                          error])
                      (parser-proc p))))]

  #:methods gen:applicative
  [(define (pure _ x)
     (pure/p x))

   (define (apply p ps)
     (do [f  <- p]
         [xs <- (map/m values ps)]
         (d:pure (r:apply f xs))))]

  #:methods gen:monad
  [(define (chain f p)
     (parser
      (λ (input)
        (match (parse p input)
          [(empty (ok (and foo (syntax-box x _)) rest message))
           (match (parse (f x) rest)
             [(empty reply) (empty (merge-message/reply message reply))]
             [consumed      consumed])]
          [(consumed (ok (and foo (syntax-box x srcloc)) rest message))
           (consumed (match (parse (f x) rest)
                       [(consumed (ok stx rest message))
                        (ok (merge-syntax-box/srcloc stx srcloc) rest message)]
                       [(empty (ok (syntax-box datum _) rest message))
                        (merge-message/reply message (ok (syntax-box datum srcloc) rest message))]
                       [(consumed error) error]
                       [(empty error) (merge-message/reply message error)]))]
          [error error]))))])

Это определяет тип структуры с именем parser, содержащий одно поле proc, и реализует gen:functor, gen:applicative и gen:monad интерфейсы для этого типа структуры.В одном поле содержится процедура синтаксического анализа.

...