На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU, ANDLL, fatalist
Страницы: (4) 1 [2] 3 4  все  ( Перейти к последнему сообщению )  
> Изучаю Haskell
    Очередная шифрограмма от Хаскелл :D
    ExpandedWrap disabled
      words _ [] = []
      words p s = w : words p s'
          where
              (w, s') = f p $ dropWhile p s
              f p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = f p xs
              f _ xs = ([], xs)

    Что она делает? Получает предикат сравнения, строку, и возвращает список слов.. все :blink: так коротко? я кайфую :hang:
    ExpandedWrap disabled
      words (==' ') "Lorem Ipsum is simply dummy text of the printing and typesetting industry."
      // ["Lorem","Ipsum","is","simply","dummy","text","of","the","printing","and","typesetting","industry."]

    Задача та же перевести на JS :wacko:

    Кстати в Хаскелле отступы имееют значение! Тут аля как их не расставишь, но у меня с этим не было проблем ибо я всегда нормально их ставил :D
    но вот те кто не любит отступы будут в га*не :lool:
    Вроде в Пайтоне также. Наверно кодеры Хаскелла и Пайтон дружат :D
    Сообщение отредактировано: Cfon -
      ExpandedWrap disabled
        'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'.split(' ')
        Цитата Serafim @
        ExpandedWrap disabled
          'Lorem Ipsum is simply dummy text of the printing and typesetting industry.'.split(' ')

        нет надо показать реализацию JS кода что привел на Haskell :D
        То что в JS есть свои функции для обработки строк, я естесно в курсе как бы не наслышке, мой здесь интерес реализовать их в функциональном стиле.
        Кстати в Хаскелле уже есть готовая функция words, я ее тут немного переклепал для практики :D

        Догадываюсь что тут мало Хаскелистов (, а может и нет вапще :D ) и приведеный мной код не понятен многим, поэтому я ща его расшифрую :D

        Короче даю построчный разбор кода
        ExpandedWrap disabled
          words _ [] = [] // 1
          words p s = w : words p s' // 2
               where
                   (w, s') = f p $ dropWhile p s // 3
                   f p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = f p xs // 4
                   f _ xs = ([], xs) // 5

        Немного поясню стиль написания функций на Хаскелл основан на совпадении образцов (patterns matching), т.е. пишутся простые выражения (уравнения), которые потом выборочно вычисляются в зависимости от совпадения.
        1 - совпадение срабатывает в случае когда words вызывается на пустом списке, он же является завершающим вызовом рекурсного вызова words
        2 - идет рекурсивный вызов words
        3 - вспомогательная функция f собственно выполняет всю работу по разделению слов, вызов dropWhile p s откидывает пробелы вначале строки s и предает ее в функцию f
        4 - идет рекурсивный вызов f в результате каждого шага рекурсии возвращется пара или говоря в терминах Хаскелля кортеж (ys, zs), далее он намного изменяется, точнее сам то кортеж не меняется, т.к. в Хаскелл нет переменных в классическом понимании, это просто некое имя для значения или выражения, создается новый кортеж (x:ys, zs) с измененым списком ys, если говорить точнее к нему в голову добавляется значение переменной x
        5 - завершающий вызов рекурсии
        еще проще сложно описать т.к. надо весь язык капать :D
        Сообщение отредактировано: Cfon -
          Приветствую вот накодил получилась жесть, как по мне что то не то :D
          ExpandedWrap disabled
            function words(p, s) {
                if (s === '') return [];
             
                function f(p, s) {
                    const a = [...s];
                    const {c, s1} = { c: a.shift(), s1: a.join('')};
              
                    if (!p(c)) {
                        const {w, s2} = f(p, s1);
                        return {w: [c,...w].join(''), s2};
                    }
                    return {w:[], s2:s1};
                };
                
                const {w, s2} = f(p, dropWhile(p, [...s]).join(''));
                return [w, ...words(p, s2)];
            }
             
            const s = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. ";
            const ws = words(c => c === ' ', s);
            console.log(ws);
            // ["Lorem","Ipsum","is","simply","dummy","text","of","the","printing","and","typesetting","industry."]

          в коде есть где то баг, если исходная строка не заканчивается пробелом, то все летит лесом :D
          ПС. dropWhile взят из прошлых моих творений что в предыдущих постах постах :D
          ладно чет устал я если у вас есть желание найти баг, ну или свой пример запостить велком, а я отдыхать! :huh:
          Сообщение отредактировано: Cfon -
            Баг нашел, дело в строчке где происходит отделение символа от строки, но пока решения не нашел, временно поставил императивный костыль :D
            ExpandedWrap disabled
              function words(p, s) {
                  if (s === '') return [];
               
                  function f(p, s) {
                      let [c, ...s1] = s; //<--- тут баг
                      if (c === undefined) c = ' '; //<-- костыль
               
                      if (!p(c)) {
                          const {w, s2} = f(p, s1);
                          return {w: [c, ...w], s2};
                      }
                      return {w:[], s2: s1};
                  };
                  
                  const {w, s2} = f(p, dropWhile(p, [...s]));
                  return [w.join(''), ...words(p, s2.join(''))];
              }

            Попутно подрихтовал код заюзав деструктиризацию массива вместо прямых манипуляций :D
            ExpandedWrap disabled
              const a = [...s];
              const {c, s1} = { c: a.shift(), s1: a.join('')};

            на
            ExpandedWrap disabled
              let [c, ...s1] = s;
            Сообщение отредактировано: Cfon -
              Цитата Cfon @
              нет надо показать реализацию JS кода что привел на Haskell

              ExpandedWrap disabled
                function *words(sentence, separator) {
                    let buffer = '';
                 
                    for (let char of sentence) {
                        if (char === separator) {
                            yield buffer;
                            buffer = '';
                            continue;
                        }
                 
                        buffer += char;
                    }
                }


              Прикреплённый файлПрикреплённый файл123123.jpg (277,2 Кбайт, скачиваний: 363)
              Сообщение отредактировано: Serafim -
                Цитата Cfon @
                Баг нашел, дело в строчке где происходит отделение символа от строки, но пока решения не нашел, временно поставил императивный костыль :D

                Пофиксил
                ExpandedWrap disabled
                  function words(p, s) {
                      if (s === '') return [];
                   
                      function f(p, s) {
                          const [c = ' ', ...s1] = s;
                              //    ^^ значение по умолчанию
                   
                          if (!p(c)) {
                              const {w, s2} = f(p, s1);
                              return {w: [c, ...w], s2};
                          }
                          return {w:[], s2: s1};
                      };
                      
                      const {w, s2} = f(p, dropWhile(p, [...s]));
                      return [w.join(''), ...words(p, s2.join(''))];
                  }

                Вроде более менее приближен к Хаскелл-стилю, надо еще подрихтовать формы :D

                Добавлено
                Цитата Serafim @
                ExpandedWrap disabled
                  function *words(sentence, separator) {
                      let buffer = '';
                   
                      for (let char of sentence) {
                          if (char === separator) {
                              yield buffer;
                              buffer = '';
                              continue;
                          }
                   
                          buffer += char;
                      }
                  }

                ну и где тут функциональный подход Хаскелл? :blink:

                очередная императивная реализация :D
                Сообщение отредактировано: Cfon -
                  Вот еще немного рихтовки :D
                  ExpandedWrap disabled
                    function words(p, s) {
                      if (s === '') return []; // 1
                     
                      const f = (p, s) => {
                        const [x = ' ', ...xs] = s;
                        return !p(x)
                          ? ({ys, zs} = f(p, xs), {ys: [x,...ys], zs}) // 4
                          : {ys:[], zs: xs} // 5
                      };
                     
                      const {ys: w, zs: s1} = f(p, dropWhile(p, [...s])); // 3
                      return [w.join(''), ...words(p, s1.join(''))]; // 2
                    }

                  Оригинал на Хаскелле
                  ExpandedWrap disabled
                    words :: (Char -> Bool) -> String -> [String]
                    words _ [] = [] // 1
                    words p s = w : words p s' // 2
                        where
                            (w, s') = f p $ dropWhile p s // 3
                             f p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = f p xs // 4
                             f _ xs = ([], xs) // 5

                  Почти один в один :D

                  В ходе исследования кода JS в попытке приблизить его в функциональному стилю Haskell должен отметить операторы запятая и тернарный, а также синтаксис деструктуризации объектов и массивов, и остаточных элементов ES6 :thanks: Без них мало что получилось! :D
                  А также группе Helloween и ушам Audio Technica! Они хорошо изолировали меня от окружающих! :D
                  Сообщение отредактировано: Cfon -
                    Пардон! Грубая ошибка! Так нельзя >:(
                    ExpandedWrap disabled
                      function words(p, s) {
                        if (s === '') return [];
                       
                        const f = (p, s) => {
                          const [x = ' ', ...xs] = s;
                          return !p(x)
                            ? ({ys, zs} = f(p, xs), {ys: [x,...ys], zs})
                             //  ^^^^^ создаются глобальные переменные!!
                            : {ys:[], zs: xs}
                        };
                       
                        const {ys: w, zs: s1} = f(p, dropWhile(p, [...s]));
                        return [w.join(''), ...words(p, s1.join(''))];
                      }

                    Обратно к корректной форме :D
                    ExpandedWrap disabled
                      function words(p, s) {
                          if (s === '') return [];
                       
                          const f = (p, s) => {
                              const [x = ' ', ...xs] = s;
                              if (!p(x)) {
                                  const {ys, zs} = f(p, xs);
                                     //   ^^^^  OK, локальные переменные
                                  return {ys: [x,...ys], zs};
                              }
                              return {ys:[], zs: xs};
                          };
                       
                          const {ys: w, zs: s1} = f(p, dropWhile(p, [...s]));
                          return [w.join(''), ...words(p, s1.join(''))];
                      }

                    Фан версия! :D
                    ExpandedWrap disabled
                      function words(p, s) {
                          if (s === '') return [];
                       
                          const f = (p, s) => (() => {
                              const [x = ' ', ...xs] = s;
                              return !p(x)
                                  ? (() => {const {ys, zs} = f(p, xs);return {ys: [x,...ys], zs}})()
                                  : {ys:[], zs: xs}
                          })();
                       
                          const {ys: w, zs: s1} = f(p, dropWhile(p, [...s]));
                          return [w.join(''), ...words(p, s1.join(''))];
                      }
                    Сообщение отредактировано: Cfon -
                      Цитата Cfon @
                      ну и где тут функциональный подход Хаскелл?

                      Он медленный, жрёт кучу оперативы и не читаемый.
                        Цитата Serafim @
                        Он медленный, жрёт кучу оперативы и не читаемый.

                        Вроде как Haskell рекурсии оптимизирует и они не жрут память, читал где то :)
                        а не читаемый потому что функциональный стиль требует иного подхода к чтению :D

                        ОК очередное задание, переписать на JS код, который парсит строку на слова и возвращает список из числа повторений каждого слова и самого слова :D
                        Вот образец
                        ExpandedWrap disabled
                          *Main> wordNums "hello world hello"
                          [(2,"hello"),(1,"world")]

                        Код на Хаскелле
                        ExpandedWrap disabled
                          wordNums :: String -> [(Int, String)]
                          wordNums s = [(length ws, head ws) | ws <- group . qsort . words (==' ') $ s]
                           
                          words :: (Char -> Bool) -> String -> [String]
                          words p s = case dropWhile p s of
                            "" -> []
                            s' -> w : words p s''
                              where (w, s'') = split p s'
                           
                          qsort :: (Ord a) => [a] -> [a]
                          qsort [] = []
                          qsort (x : xs) =
                              qsort [y | y <- xs, y <= x] ++
                              [x] ++
                              qsort [y | y <- xs, y > x]
                           
                          group :: (Eq a) => [a] -> [[a]]
                          group [] = []
                          group (x:xs) = (x:ys): group zs where (ys, zs) = split (/= x) xs
                           
                          split :: (a -> Bool) -> [a] -> ([a], [a])
                          split p (x:xs) | (not . p) x = (x:ys, zs) where (ys, zs) = split p xs
                          split _ xs = ([], xs)

                        Функции words, qsort уже переписаны на JS в предыдущих постах, я их для наглядности сюда тоже перенес. Осталось group и wordNums. Ну а split я просто вынес из words для повторного применения в group. Она делить список (строку) на две части согласно предику :D

                        Пояснения к коду Хаскелл.
                        words - получает исходную строку и возвращает список слов
                        group - получает список слов и выделяет рядом лежащие совпадающие слова в отдельные списки, ну возвращает его (список списков)
                        sort - понятно сортирует :D
                        split - уже писал выше
                        ВСЕ! да и я тоже буду переводить го кто шустрее :lool:
                        Сообщение отредактировано: Cfon -
                          Готова! :D
                          ExpandedWrap disabled
                            function words(p, s) {
                                if (s === '') return [];
                                const [w, s1] = split(p, dropWhile(p, [...s]));
                                return [w.join(''), ...words(p, s1.join(''))];
                            }
                             
                            function group(xs) {
                                if (xs.length == 0) return [];
                                const [x, ...xs1] = xs;
                                const [ys, zs] = split(x1 => x1 !== x, xs1);
                                return [[x, ...ys], ...group(zs)];
                            }
                             
                            function split(p, xs) {
                                if (xs.length == 0) return [[],[]];
                                const [x, ...xs1] = xs;
                                if (!p(x)) {
                                    const [ys, zs] = split(p, xs1);
                                    return [[x, ...ys], zs];
                                }
                                return [[], xs];
                            }
                             
                            function dropWhile(p, xs) {...} // см выше
                            function qsort(xs) {...} // см quicksort
                             
                            const wordNums = s =>
                                group( qsort( words(c => c == ' ', s))).map(ws => ([ws.length, ws[0]]));
                             
                            const s = 'hello world hello';
                            console.log(wordNums(s));
                            // [ [ 2, 'hello' ], [ 1, 'world' ] ]

                          Получилось почти в функциональном стиле, почему почти? :D
                          1 - в функциях больше одного return
                          2 - наличие присваиваний
                          Все это вносит некий императизм :D
                          Но несмотря на это в обшем код смотрится функционально! :blush:
                          Особенно функция wordNums изящно не правда ли? :wizard:
                          Сообщение отредактировано: Cfon -
                            Цитата Cfon @
                            Вроде как Haskell рекурсии оптимизирует и они не жрут память, читал где то

                            А зачем оптимизировать что-то, если можно просто вернуть корутину?

                            Добавлено
                            Цитата Cfon @
                            Но несмотря на это в обшем код смотрится функционально!

                            Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... Хотя, постой, кажется, я уже это делал :whistle:
                              Цитата Serafim @
                              Код смотрится отвратно. Я могу сократить его в 10 раз и сделать на порядки читаемее... Хотя, постой, кажется, я уже это делал :whistle:

                              Го жду :D
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (4) 1 [2] 3 4  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0592 ]   [ 16 queries used ]   [ Generated: 19.04.24, 16:40 GMT ]