1

flatMap подпись:Функциональная подпись flatMap (input -> output) предлагает выполнить любое сглаживание?

/* applies a transformation of the monad "content" by composing 
    * this monad with an operation resulting in another monad instance 
    * of the same type 
    */ 
    def flatMap(f: A => M[B]): M[B] 

есть в любом случае, чтобы понять его подписью (вход для вывода), что его уплощение структуры (для имени flat исключением)? или я должен прочитать его реализацию, чтобы понять это? не является хорошей практикой кодирования, я могу понять по сигнатуре функции (ввод для вывода даже без имени функции) именно то, что она делает? если да, то как flatMap следует этой базовой практике программирования? или делает это нарушает it?

+0

Если вы просто используете 'map' с' f: A => M [B] ', вы получите« M [M [B]] '. Так что с 'flatMap' вы выравниваете – mfirry

+1

' flatMap' эквивалентно 'join (map fm)' где 'join' имеет тип' M [M [A]] => M [A] ', поэтому он не сглаживает структура ввода, а скорее отображаемая структура. Это не сразу видно из типа 'flatMap'. – Lee

+0

Что еще можно сгладить? – gallais

ответ

6

Это помогает понять, что тип вещи, что flatMap определяется на также M и будет что-то вроде Traversable[A] или подкласса таких как List[A] или другой Монада, такие как Option или Future. Поэтому левая часть определения функции, которую требует flatMap (f: A => M[B]), подсказывает нам, что эта функция обрабатывает отдельные элементы, содержащиеся в Monad, и производит M [B] для каждого из них. Тот факт, что он затем возвращает M[B], а не M[M[B]], - это намек на то, что происходит некоторое сглаживание.

Однако я не согласен с тем, что должно быть возможно точно знать, что делает функция по его подписи. Например:

Trait Number { 
    def plus(that: Number): Number 

    def minus(that: Number): Number 
} 

Без названия функций и возможно также некоторые документы, я не думаю, что это разумно ожидать, что другой человек может знать, что plus и minus делать.

+2

Чтобы добавить к вашей точке, что подписи функции не все (+1 кстати): монады определяются их ** алгеброй **, то есть набором операций ('flatMap',' map', 'unit' , и т. д.) и законы * операции * (например, 'flatMap' является ассоциативным и имеет левую идентификацию и правильное удостоверение личности). Подпись метода передает операцию монады, но не ее законы. – dcastro

3

Функциональная подпись flatMap (input -> output) предлагает выполнить любое сглаживание?

Да, это так. Фактически, join (или flatten), map и unit образуют минимальный набор примитивных функций, необходимых для реализации монады. flatMap может быть реализован с точки зрения этих других функций.

//minimal set 
def join[A](mma: M[M[A]]): M[A] = ??? 
def map[A](ma: M[A], f: A => B): M[B] = ??? 
def unit[A](a: A): M[A] = ??? 

def flatMap[A](ma: M[A], f: A => M[B]): M[B] = join(map(ma)) 

Это теперь должно быть ясно, что flatMapсглаживает структуру отображенной монады.

Для сравнения, вот еще один набор примитивов, в котором join/flatten реализован в терминах flatMap.

// minimal set 
def unit[A](a: A): M[A] = ??? 
def flatMap[A](ma: M[A], f: A => M[B]): M[B] = ??? 

def map[A](ma: M[A], f: A => B): M[B] = flatMap(ma, a => unit(f(a))) 
def join[A](mma: M[M[A]]): M[A] = flatMap(mma, ma => ma)