2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3
 
 Re: Mонады в javascript
Сообщение10.06.2015, 23:50 


11/12/14
893
arseniiv в сообщении #1025858 писал(а):
Просто, видимо, в следующем заходе вернитесь к «не улучшенной» версии из статьи про Python.


В "не улучшенной" версии я вынужден под каждую монаду писать свой набор функций с ней работающий. Или пропихивать в каждую такую функцию конструктор монады. Тоже можно рассмотреть как вариант, но в целом как то тоже не очень.
P.P.S.
Да, вот вы выложили свой вариант - он короче именно потому что range это специальная функция уже возвращающая монаду. У меня сложнее именно на то, что нужная монада создаётся по месту, а genarray обычная функция, ничего о монадах не знающая, как параметр.

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение10.06.2015, 23:51 


05/09/12
2587
arseniiv в сообщении #1025868 писал(а):
Эх, если бы в JS были бы макросы

Используется синтаксис Lisp
(defn return (x) (cons x nil))
(defn bind (l f) (concat (map f l)))
(def <- (macro (_n _v _e) (bind _v (lambda (_n) _e))))

(defn do-example (n)
    (<- a (list-from-to 1 n)
    (<- b (list-from-to 1 a)
    (cons (cons a b) (cons (cons b a) nil)) )))
(printLn (do-example 3))

Код:
((1 1) (1 1) (2 1) (1 2) (2 2) (2 2) (3 1) (1 3) (3 2) (2 3) (3 3) (3 3))

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение10.06.2015, 23:52 


11/12/14
893
arseniiv в сообщении #1025868 писал(а):
предполагается, что bind и не используемый здесь return добавили в Array.prototype


А, даже хитрее. Тогда монады, как отдельного класса и нет, есть просто массив с обновлёнными методами. Ну тоже хлеб интересный.

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 00:08 
Заслуженный участник


27/04/09
28128
Кстати говоря, некоторые монады позволяют прервать вычисления — например, та же Maybe с помощью внедрения пустого значения, или монада ошибки, которая вместо пустого значения имеет какую-то информацию и т. д.. Для них используется класс
Используется синтаксис Haskell
class Monad m => MonadZero m where
  mzero :: m a
  // должно выполняться mzero >>= k = mzero

Для прерывания вычислений вставляется mzero, после чего дальше всё >>=е пропускается благодаря лени (раз второй аргумент не нужен, не будем вычислять — и тут в JS может получиться упс в некоторых случаях (если только не реализовать force/delay, запутывая всё окончательно; и, опять же, нет макросов для определения delay)). Для улучшения этого есть функция
Используется синтаксис Haskell
guard :: MonadZero m => Bool -> m ()
guard False = mzero
guard True = return ()
использующаяся, например, так:
Используется синтаксис Haskell
filteredPairs :: [Name] -> [Fruit] -> (Fruit -> Bool) -> (Name -> Fruit -> Bool) -> [(Name, Fruit)]
filteredPairs names fruits isEdible likes = do
  fruit <- fruits
  guard (isEdible fruit)
  name <- names
  guard (likes name fruit)
  return (name, fruit)

Пример немного искуственный и может быть заменён в этом случае на list comprehension, раз уж тут снова список-монада.

aa_dav в сообщении #1025871 писал(а):
А, даже хитрее. Тогда монады, как отдельного класса и нет, есть просто массив с обновлёнными методами. Ну тоже хлеб интересный.
Именно. В смысле ООП это скорее интерфейс, как я выше говорил. :-) А классы и другие типы могут быть только инстансами её. Т. к. JS динамический по части интерфейсов, его как бы и не надо нигде писать, только молясь о правильном понимании слов bind и return инстансописателем.

aa_dav в сообщении #1025869 писал(а):
Да, вот вы выложили свой вариант - он короче именно потому что range это специальная функция уже возвращающая монаду.
Но так и должно быть. Опять же, как я уже писал, справа от стрелочки выражение типа m a.

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 00:14 
Заслуженный участник
Аватара пользователя


01/09/13
4656
Скажите, а где на практике это можно практично применить??

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 00:24 


11/12/14
893
Да, теперь уложилось понимание.
В хаскелле bind просто и тупо смотрит на свои аргументы и срабатывает для инстанса, но главное что левый аргумент может быть не самим инстансом - а то что там в аргументах замучено. Действительно скорее миксины, чем какие то классы. И тут перегрузка прототипа в яваскрипте очень удачно сыграло.
С другой стороны неимение такого механизма просто заставляет нас в яваскрипте bind пристёгивать как метод... к тому что было левым аргументом в хаскеле.
И таким образом первая функция возвращающая монадический тип начинает "раскручивать" последовательность вызовов.

Такс, и поглядев еще раз на примеры монад Хаскеля вижу что там как раз предполагается что функция вернет монаду. Значит видимо вот оно и есть - функции работающие с монадами должны возвращать монады. Уже припоминаю что есть вроде как обёртки. Тогда да, первичный пайтоновский вариант лучше соответствует тому что в хаскелле происходит - это был не баг, как я подумал, а фича.

-- 11.06.2015, 01:24 --

Geen в сообщении #1025884 писал(а):
Скажите, а где на практике это можно практично применить??


В Хаскелле. В яваскрипте не нужно. Я лично в теме участвую исключительно для улучшения понимания.

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 00:32 
Заслуженный участник
Аватара пользователя


01/09/13
4656
aa_dav в сообщении #1025892 писал(а):
В яваскрипте не нужно.

Гм, а это, часом, не оффтоп тогда? :-)

-- 11.06.2015, 00:35 --

Я не занудствую, я просто что-нибудь рациональное пытаюсь найти :-)

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 02:08 
Заслуженный участник


27/04/09
28128
Geen в сообщении #1025884 писал(а):
Скажите, а где на практике это можно практично применить??
Здесь монады ушли недалеко от строк или каких-нибудь контейнеров: где угодно, это строительный материал. В данном случае обычно для «строительства» логики. Можно удариться в детали по каждой из монад, если хотите (но я про все не расскажу). Потом, ещё стрелки есть со своим сахаром и комонады с пока не реализованным предложенным сахаром, и просто аппликативные функторы, которые и без сахара нормально выглядят, и… и…

aa_dav в сообщении #1025892 писал(а):
Да, теперь уложилось понимание.
В хаскелле bind просто и тупо смотрит на свои аргументы и срабатывает для инстанса, но главное что левый аргумент может быть не самим инстансом - а то что там в аргументах замучено.
Видать, не совсем ещё уложилось. :wink: Тут инстансом будет ненаселённый (нет значений) тип [] List, потому что кинд его не * , а * -> *. Т. е. левый аргумент не то что может быть не инстансом, он даже не будет им никогда, а будет результатом применения к List какого-то *-типа. (Ну и иногда инстансы — это наборы нескольких типов, так что так говорить стоит с осторожностью, хотя я первый начал.)

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 06:22 


11/12/14
893
Geen в сообщении #1025899 писал(а):
Гм, а это, часом, не оффтоп тогда?


Тема называется "монады в яваскрипт". =) О каком оффтопе речь? =)
Рациональное зерно тоже есть - иногда императивному программисту хочется хотя бы глазком увидеть - что там за монады все обсуждают в темах про ФЯ - тут можно хотя бы примерно понять в чём суть, хотя, опять таки, без хаскелля оно и не нужно в реальном коде на том же яваскрипте.

arseniiv в сообщении #1025931 писал(а):
Видать, не совсем ещё уложилось.


Ну я некорректно выразился. У меня ранее много непонимания было как раз потому что я думал, что тип монады он как какой то класс (поэтому пытался увидеть как генератор списка куда то утягивается внутрь монады чтобы породить именно типа эээ... "Monade[a]". А на деле совсем по другому, да.

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 09:36 
Заслуженный участник


27/04/09
28128
Охотно верю, что ситуация улучшилась ещё тогда, просто решил доиграть в корректность. :-)

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 09:59 


11/12/14
893
Сошёл с ума и реализовал пример с List на C++. %)
Самое интересное что в С++ operator>>= можно так сказать перегрузить для того же vector типа "неинтрузивно", что оно не затрагивает сам тип vector...
Но невозможность вывести тип на ходу заставляет вменять тип по месту использования и получается еще большая жуть. =)

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
#include <vector>
#include <functional>

template< class T, class U >
std::vector<U> operator>>=( std::vector<T> val, std::function<std::vector<U>(T)> f )
{
        std::vector<U> res;
        for( auto x: val )
        {
                std::vector<U> subs = f( x );
                for ( auto y: subs )
                {
                        res.push_back( y );
                };
        };
        return res;
};

std::vector<int> genarray( int n )
{
        std::vector<int> res;
        for ( int i = 1; i <= n; i++ )
                res.push_back( i );
        return res;
};

template< class T >
struct mpair
{
        T a, b;
        mpair( T na, T nb ): a(na), b(nb) {};
};
               
std::vector<mpair<int>> example( int n )
{
        return genarray( n ) >>= std::function<std::vector<mpair<int>>(int)>( [&](int a){ return genarray(a) >>= std::function<std::vector<mpair<int>>(int)>([&](int b) { return std::vector<mpair<int>>{ mpair<int>(a,b), mpair<int>(b,a) }; } ); } );
};

int main()
{
        auto r = example( 3 );
        for ( auto x: r )
                std::cout << "(" << x.a << "," << x.b << ")";
};
 


Но таки да, работает: http://ideone.com/THHT0i

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение11.06.2015, 23:41 


05/09/12
2587
Ну раз уж с С++ не оффтоп, то я со своим лискриптом снова влезу - подсыпал еще немного макросового сахара в do-нотацию а-ля хаскель:
код: [ скачать ] [ спрятать ]
Используется синтаксис Lisp
(defn return (x) (cons x nil))
(defn bind (l f) (concat (map f l)))
 
(defn foldapp (l)
    (cond (null? (car (cdr l))) (car l)
          (append (deinfix (take 3 l)) (cons (foldapp (drop 3 l)) nil)) ))
 
(defn deinfix (l) (cons (car (cdr l)) (cons (car l) (cdr (cdr l)))) )
 
(def do (macro (_l) (eval (foldapp '_l))))
 
(def <- (macro (_n _v _e) (bind _v (lambda (_n) _e))))
 
(defn do-example (n) (do (
    a <- (list-from-to 1 n)
    b <- (list-from-to 1 a)
    c <- (list-from-to 1 b)
    (cons (cons c (cons b a)) nil)
)))
(printLn (do-example 3))
 
((1 1 1) (1 1 2) (1 2 2) (2 2 2) (1 1 3) (1 2 3) (2 2 3) (1 3 3) (2 3 3) (3 3 3))
 

 Профиль  
                  
 
 Re: Mонады в javascript
Сообщение12.06.2015, 08:28 


11/12/14
893
P.S.
Напомнили на другом форуме что как раз для подобных случаев в С++11 добавили delctype. Код тогда становится много более вменяемым:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
template< class T, class F >
auto operator>>=( std::vector<T> val, F f )->decltype( f(val[0]) )
{
  decltype( f(val[0]) ) res;
  for( auto x: val )
  {
    decltype( f(val[0]) ) subs = f( x );
    for ( auto y: subs )
    {
      res.push_back( y );
    };
  };
  return res;
};

std::vector<mpair<int>> example( int n )
{
  return genarray( n ) >>= [&](int a){ return genarray(a) >>= [&](int b) { return std::vector<mpair<int>>{ mpair<int>(a,b), mpair<int>(b,a) }; }; };
};
 

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 43 ]  На страницу Пред.  1, 2, 3

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group