На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
  
> Изучаю Haskell
    Здрасте!

    начал изучать Haskell :D
    вот пытаюсь перевести на JS код с Haskell но тока в функциональном стиле JS
    ExpandedWrap disabled
      nouns = ["frog","raven","ribbit"]
      adjectives = ["lazy","angry","tiny","happy","shy"]
      mixin nouns adjectives = [adj ++ " " ++ noun | adj <– adjectives, noun <– nouns]

    Выхлоп
    ExpandedWrap disabled
      [ "lazy frog","angry frog","tiny frog","happy frog","shy frog",
      "lazy raven","angry raven","tiny raven","happy raven","shy raven",
      "lazy ribbit","angry ribbit","tiny ribbit","happy ribbit","shy ribbit" ]


    Пробую через Array,reduce, пока стена :wall:
      Сам порешал :D
      ExpandedWrap disabled
        function mixin(nouns, adjs) {
            return nouns.reduce((a, noun) => {
              const v = adjs.map(adj => {
                return adj + ' ' + noun;
              });
              return [...a, ...v];
            }, []);
        }


      На хаскелле как то более проще думать такие задачи, лямбда исчисление рулит! :whistle:

      Haskell:
      ExpandedWrap disabled
        mixin nouns adjs = [adj ++ " " ++ noun | adj <– adjs, noun <– nouns]

      Так изменил в более функциональный стиль JS, но все равно не так очевидно как на Хаскеле :D
      ExpandedWrap disabled
        const mixin = (nouns, adjs) => nouns.reduce((a, noun) => [...a, ...adjs.map(adj => adj + ' ' + noun)], []);
      Сообщение отредактировано: Cfon -
        Продолжаю изучать удивительный Haskell! :D
        Еще одна задачка на поиск прямоугольных треугольников, дано три списка с числами от 1 до 10 например, надо найти все совпадения прямоугольных треугольников. На хаскеле изи! :D
        ExpandedWrap disabled
          aa =[1..10]
          bb = [1..10]
          cc = [1..10]
          triples aa bb cc = [(a,b,c) | a <- aa, b <- bb, c <- cc, a^2 + b^2 == c^2]

        Выхлоп
        ExpandedWrap disabled
          [(4,3,5),(3,4,5),(8,6,10),(6,8,10)]

        Как теперь это на JS написать? :wacko:

        Добавлено
        Переключил моск с функционального на императивный режим :lool:
        Оказывается тут идет тупой перебор по трем циклам :D
        ExpandedWrap disabled
          const aa = [1,2,3,4,5,6,7,8,9,10];
          const bb = [1,2,3,4,5,6,7,8,9,10];
          const cc = [1,2,3,4,5,6,7,8,9,10];
           
          function triples(aa, bb, cc) {
            var v=[];
            aa.forEach(a => {
              bb.forEach(b => {
                cc.forEach(c => {
                  if ((a*a + b*b) === c*c) {
                    v.push([a,b,c]);
                  }
                });
              });
            });
            return v;
          }
        Сообщение отредактировано: Cfon -
          Одно замечание по коду, в Хаскеле все функции автоматически каррируются :D
          на JS это будет выглядеть так
          ExpandedWrap disabled
            // Каррированная версия triples
            function triples(aa) {
              return bb => {
                return cc => {
                  var v = [];
                  aa.forEach(a => {
                    bb.forEach(b => {
                      cc.forEach(c => {
                        if ((a*a + b*b) === c*c) {
                          v.push([a,b,c]);
                        }
                      });
                    });
                  });
                  return v;
                };
              };
            }
             
            triples(aa)(bb)(cc);

          зачем Хаскель это делает? :blink:
          да хз я еще не дошел до этого... вроде бы это связано с его реализацией, а именно лямбда функциями :unsure:
          в данном коде на JS это делать не обязательно :D
          Сообщение отредактировано: Cfon -
            Разобрался зачем :D
            Для того чтобы юзать их в функциях высшего порядка, например
            ExpandedWrap disabled
              const result = [[1,2,3,4,5],[6,7,8,9,10]].map(triples(aa)(bb));
              console.log(result);
              // [[[ 3, 4, 5 ]], [[ 6, 8, 10 ]]]


            ну а на Haskell все проще :D
            ExpandedWrap disabled
              map (triples aa bb) [[1..5],[6..10]]
              // [[(3,4,5)],[(6,8,10)]]


            Кто не понял объясняю, каррированная функция передается функции высшего порядка путем частичного применения :blush:

            Добавлено
            Очередной вопрос, вот на Haskell код так называемой быстрой сортировки
            ExpandedWrap disabled
              quicksort [] = []
              quicksort (x : xs) =
                  quicksort [a | a <- xs, a <= x] ++
                  [x] ++
                  quicksort [a | a <- xs, a > x]


            как его переделать на JS :wacko:
            Сообщение отредактировано: Cfon -
              Вот вам функционально-подобная попытка на JS приблизится к великому Хаскеллу :D
              ExpandedWrap disabled
                function quicksort(array) {
                    if (array.length === 0) return [];
                    
                    const origin = [...array];
                    const elem0 = origin.pop();
                    const left = origin.filter(elem => elem < elem0);
                    const right = origin.filter(elem => elem >= elem0);
                 
                    return [...quicksort(left), elem0, ...quicksort(right)];
                }
                 
                var nums = [10,2,5,3,1,6,7,4,2,3,4,8,9];
                var sortedNums = quicksort(nums);
                console.log(nuts);       // [ 10, 2, 5, 3, 1, 6, 7, 4, 2, 3, 4, 8, 9 ]
                console.log(sortedNums); // [ 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10 ]


              И все равно императивный стиль JS присутствует :D
              Сообщение отредактировано: Cfon -
                Для евангелистов reduce коим являюсь сам :D, вот более оптимизированая версия за счет одного цикла, вместо двух в случае с filter:
                ExpandedWrap disabled
                  function quicksort(array) {
                      if (array.length === 0) return [];
                      
                      const origin = [...array];
                      const elem0 = origin.pop();
                   
                      var res = origin.reduce((aa, elem) => (
                          (elem < elem0)
                              ? [[...aa[0], elem], aa[1]]
                              : [aa[0], [...aa[1], elem]]
                      ), [[],[]]);
                      
                      return [...quicksort(res[0]), elem0, ...quicksort(res[1])];
                  }

                Цикла? :facepalm:
                Да-да не удивляйтесь! В JS все равно надо переключаться в императивный режим :jokingly:
                Сообщение отредактировано: Cfon -
                  Продолжаю переносить задачки из Хаскель на JS :D

                  вот исходная задачка на удаление определенного числа элементов из списка с использованием рекусии:
                  ExpandedWrap disabled
                    drop 0 xs = xs
                    drop _ [] = []
                    drop n (x:xs) = drop (n-1) xs

                  а вот та же но через foldl (это аналог reduce в JS)
                  ExpandedWrap disabled
                    drop 0 xs = xs
                    drop _ [] = []
                    drop n xs = foldl (\xs _ -> tail xs) xs [1..n]

                  С рекурсией на JS не было проблем
                  ExpandedWrap disabled
                    function drop(n, array) {
                        if (n === 0) return array;
                        if (array.length == 0) return [];
                        
                        array.shift();
                        return drop(n-1, array);
                    }
                     
                    drop(1, [1,2,3]) // [2,3]

                  а вот как сделать тоже но через reduce? :wacko:

                  Небольшая поправочка в Хаскелле все данные иммутабельны, а у меня тут исходный массив array меняется, что не в Хаскел-стиле! Правим:
                  ExpandedWrap disabled
                    function drop(n, array) {
                        const origin = [...array];
                        if (n === 0) return origin;
                        if (array.length == 0) return [];
                        
                        origin.shift();
                        return drop(n-1, origin);
                    }
                  Сообщение отредактировано: Cfon -
                    :lool: ВСЕ ПРОСТО!! я забыл что в JS можно изменять состояние, это ж не Хаскель :facepalm:
                    Мде сложно переключаться с функционального на императивный режим, надо тернироваться :D
                    Вот решение, получается еще проще чем в Хаскелле
                    ExpandedWrap disabled
                      function drop(n, array) {
                          if (n === 0) return array;
                          if (array.length == 0) return [];
                       
                          return array.reduce((accum, elem) =>
                              (n-- > 0) ? accum : [...accum, elem], //<--- ВОТ ТУТ ИЗМЕНЯЕМ n.
                          []);
                      }

                    или через filter еще проще :D
                    ExpandedWrap disabled
                      function drop(n, array) {
                          if (n === 0) return array;
                          if (array.length == 0) return [];
                          
                          return array.filter(() => (n-- <= 0));
                      }

                    да и начальные условия тут тоже можно опустить :D
                    ExpandedWrap disabled
                      function drop(n, array) {  
                          return array.filter(() => (n-- <= 0));
                      }


                    Хотя я погорячился сказав что проще Хаскеля не проще! куда ж еще проще? :blink:
                    ExpandedWrap disabled
                      drop n xs = foldl (\(_:xs) _ -> xs) xs [1..n]


                    Да в JS уже есть функция удаления splice, но моя цель перевести с Haskell на JS в функциональном стиле, хотя в предыдущих вариантах был применен полу императивный стиль, а не фунциональный и решение в Haskell стиле требует еще покумекать :scratch:
                    ну т.е. сделать без мутации переменной n.
                    Сообщение отредактировано: Cfon -
                      Так так так... ща рожу... а не показалось :lool:
                      1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script Execution time: 0,1374 ]   [ 14 queries used ]   [ Generated: 22.10.18, 18:36 GMT ]