2017-02-05 14 views
1

Я изучаю теорию категорий. Я понимаю концепцию читателя монады, это даже довольно легко реализовать:Читатель монады - как он соответствует интерфейсу Monad?

case class Reader[DEP, A](g: DEP => A) { 
    def apply(dep: DEP): A = g(dep) 

    def map[B](f: A => B): Reader[DEP, B] = Reader(dep => f(apply(dep))) 

    def flatMap[B](f: A => Reader[DEP, B]): Reader[DEP, B] = Reader(dep => f(apply(dep)) apply dep) 
} 

Однако, у меня есть проблемы, реализующие его с ограничением в какой-то общий интерфейс Монады, т.е.

trait Monad[A] { 
    def pure(a: A): Monad[A] 

    def map[B](f: A => B): Monad[B] 

    def flatMap[B](f: A => Monad[B]): Monad[B] 
} 

давайте забыли для во-вторых, есть аппликативный или функтор, и давайте просто поместим эти 3 метода здесь.

Теперь, имея этот интерфейс, у меня возникают проблемы с внедрением ReaderMonad. Метод карты довольно несгибаемый, но как насчет чистой и плоской карты? Что это значит для чтения на чистом? Чтобы реализовать flatMap, мне нужно иметь функцию от A до Reader [DEP, B], но у меня есть A => Monad [B], поэтому я не могу получить доступ.

case class Reader[DEP, A](g: DEP => A) extends Monad[A] { 
    def apply(dep: DEP): A = g(dep) 

    override def pure(a: A): Reader[DEP, A] = Reader(_ => a) // what does it even mean in case of Reader 

    override def map[B](f: (A) => B): Reader[DEP, B] = Reader(dep => f(apply(dep))) 

    override def flatMap[B](f: (A) => Monad[B]): Reader[DEP, B] = ??? // to implement it, I need f to be (A) => Reader[DEP, B], not (A) => Monad[B] 
} 

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

+0

Я бы посмотрел на собственную реализацию и посмотрел, как они это делают. Если вы знаете Haskell (и даже если вы этого не сделаете), возможно, стоит взглянуть на определение своего читателя Монады для подсказок. – Carcigenicate

+0

Ну, они используют совершенно другой синтаксис (в основном, классные классы), поэтому я не уверен, что поможет – slnowak

+0

. Основная проблема заключается в том, что ваша черта «Монады» неверна, поэтому вы не можете реально реализовать это без кастинга, как вы нашли , Обычная реализация заключается в параметризации символа «Монад» с помощью конструктора типов и его определения для «Reader [DEP, _]». – Lee

ответ

2

Как вы обнаружили при попытке реализовать flatMap, проблема с объявлением функции Monad как у вас есть, вы теряете определенный тип монады, который вы определяете при операции цепочки. Обычный способ определения свойства Monad состоит в том, чтобы параметризовать его конструктором типа, который определяет экземпляр монады, например.

trait Monad[M[_]] { 
    def pure[A](a: A): M[A] 
    def map[A, B](f: A => B, m: M[A]): M[B] 
    def flatMap[A, B](f: A => M[B], m : M[A]): M[B] 
} 

Так M является унарным конструктором типа, таким как List или Option. Вы можете думать о Reader[DEP, A] как о вычислении, которое зависит от некоторого типа среды DEP, который возвращает значение типа A. Так как это имеет два параметра типа вам нужно исправить тип параметра среды при определении монады экземпляра:

case class Reader[DEP, A](g: DEP => A) 

class ReaderMonad[DEP]() extends Monad[({type t[X] = Reader[DEP, X]})#t] { 
    def pure[A](a: A) = Reader[DEP, A](_ => a) 
    def map[A, B](f: A => B,m: Reader[DEP,A]): Reader[DEP,B] = Reader(env => f(m.g(env))) 
    def flatMap[A, B](f: A => Reader[DEP,B],m: Reader[DEP,A]): Reader[DEP,B] = Reader(env => f(m.g(env)).g(env)) 
} 

({type t[X] = Reader[DEP, X]})#t является type lambda используется частично применить один из двух параметров для Reader[DEP, A].

В настоящее время pure возвращает Reader, который игнорирует окружающую среду и возвращает данное значение напрямую.

flatMap создает Reader, который при запуске запускает внутреннее вычисление, использует результат для построения следующего вычисления и запускает его с той же средой.

+0

Спасибо! Этот тип лямбда выглядит ... интересным, по крайней мере. – slnowak

+2

Поздравляем с 100K! –

+0

@YuvalItzchakov - Спасибо! – Lee

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

  • Нет связанных вопросов^_^