1. Куча / Говнокод #12192

    +125

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    splitOn :: (a -> Bool) -> [a] -> [[a]]
    splitOn _ [] = []
    splitOn f xs = removeEmpty $ takeWhile (not . f) xs: splitOn f (dropWhile (f) $ dropWhile (not . f) xs) where
    	removeEmpty [] 	= []
    	removeEmpty (x:xs) 
    		| null x 	= removeEmpty xs 
    		| otherwise = x: removeEmpty xs
    
    words' :: String -> [String]
    words' = splitOn (flip elem " \n\r\f\t\v\160")

    Еще один words'

    Запостил: Fai, 25 Ноября 2012

    Комментарии (68) RSS

    • removeEmpty = filter (not . null)

      (takeWhile (not . f) xs, dropWhile (not . f) xs) = break xs

      Итого:
      splitOn :: (a -> Bool) -> [a] -> [[a]]
      splitOn f s = case break f $ dropWhile f s of
              ([], _) -> []
              (h, t) -> h : splitOn f t
      http://ideone.com/C6z4N9
      Ответить
      • зачем вы все время прописываете сигнатуры, если между модулями все равно не экспортируете?
        Ответить
        • Компилятор ошибки выдает короче, вменяемей, и во время описания, а не во время первого использования.
          Ответить
        • > зачем

          Я пишу сигнатуру до написания функции, т.к. это дает ряд преимуществ:
          1. По сигнатуре можно приблизительно понять, что делает функция, следовательно, если написать сигнатуру, будет проще затем написать саму функцию.
          2. Сигнатура четко говорит компилятору, что мне требуется именно такая функция и это не дает мне ошибиться.
          3. Нельзя также упускать из виду проблему let-связанного полиморфизма. Случается она конечно редко, но все-же.

          В итоге идеальным решением будет написать сигнатуру перед написанием функции, а затем по-желанию убрать.
          Ответить
          • >Нельзя также упускать из виду проблему let-связанного полиморфизма.
            например?
            let a = read str
            let b = show a
            ?
            И как тут поможет сигнатура функци? Имхо сам как-бы глупость написал.
            Ответить
            • А ну да, про let-bound я ошибся. Я имел ввиду ограничение мономорфизма.

              Например для кода
              add = (+)


              Компилятор выведет тип:
              add :: Integer -> Integer -> Integer


              Но он слишком частный. Почему он не вывел:
              Num a => a -> a -> a


              А все это ограничение.

              В ghc есть специальный ключ, убирающий это ограничение - XNoMonomorphismRestriction, но это не по стандарту, так-что лучше просто записать сигнатуру.
              Ответить
              • А зачем ввели мономорфизм? Это же не удобно. Мне тоже больше нравится последняя сигнатура
                Ответить
                • Его не вводили специально, это ограничение типизации в хаскеле (и по-моему вообще в типизации Хиндли-Милнера).

                  Единственное - можно от него избавиться либо указав компилятору "ты дурак, вот он правильный тип" либо сказав "ты молодец, только вот XNoMonomorphismRestriction".
                  Ответить
                  • А если ключик XNoMonomorphismRestriction использовать? Num a => a -> a -> a выведет?
                    Ответить
                    • > XNoMonomorphismRestriction использовать

                      Да выведет правильный тип.
                      Ответить
                  • >Его не вводили специально
                    А какой плюс в этом? Помоему больше минусов, чем плюсов.
                    Ответить
                    • > А какой плюс в этом?

                      Никаких плюсов, это ограничение ввелось само-собой случайно, не по воле авторов стандарта или трансляторов.

                      Я вообще надеюсь, что в следующем стандарте или в следующей версии ghc это ограничение будет снято по-умолчанию.
                      Ответить
              • К слову, никаких ошибок компиляции, он все до Float поднял (имхо как-то не правильно):
                http://ideone.com/DT7x1V
                http://ideone.com/aZ3Flk
                Но если указать сигнатуру, или NoMonomorphismRestriction , то все нормально:
                http://ideone.com/OIh4L7
                http://ideone.com/M9mKx6
                {-# LANGUAGE NoMonomorphismRestriction #-}
                 
                ad = (+)
                 
                main = do 
                        print $ ad 1 2
                        print $ ad 1 2.0
                Ответить
                • Странно. Во, вспомнил. Посмотри еще тип
                  "eq = (==)"

                  Офигеешь.
                  Prelude> let eq = (==)
                  Prelude> :t eq
                  eq :: () -> () -> Bool
                  Ответить
                  • Вот и я говорю странно. Теперь всегда NoMonomorphismRestriction использовать буду.
                    А вот ad::(Num a) => a -> a -> a как-то не кузяво.
                    Ответить
                  • Ну тут все логично. Проверь тип eq в
                    let eq = (==) in eq 1 5
                    и у тебя все станет на свои места.
                    Ответить
                    • Не логично. С ключом выводит правильный тип:
                      eq :: Eq a => a -> a -> Bool
                      Ответить
                      • Да не. Все верно. Это он просто нигде eq не использовал, поэтому тип не правильный. Считает, если не использовать нигде, что этот тип от (). А если используешь на интах, то выведет правильно eq :: Integer -> Integer -> Bool
                        Ответить
                        • Врешь. Дело опять в ограничении мономорфизма. Вот так (без использования) он выводит правильный тип:
                          Prelude> let eq a b = a == b
                          Prelude> :t eq
                          eq :: Eq a => a -> a -> Bool
                          Ответить
                          • Мономорфизм не нужен. А так да, из-за мономорфизма он и вывел эти (). Я об этом и сказал.
                            Ответить
                • Ну а Float и Double тоже инстанс Num. А числовые литералы невозбранно подходят в любом контексте, где требуется Num. Если вместо литералов поюзаешь интовую и флоатовую переменные - все обломается.

                  P.S. А вообще да, поднимать надо до Rational.
                  Ответить
                  • >А вообще да, поднимать надо до Rational.
                    Зачем? Обощённого варианта ad::(Num a) => a -> a -> a должно хватить на всех. До него надо поднимать, имхо.
                    Ответить
                    • ad надо поднять до того класса, где есть оператор (+), следовательно до Num.
                      Ответить
                  • >поюзаешь интовую и флоатовую переменные
                    Переменные в моём чистом хацкеле! No Way!
                    Ответить
                • Кстати включай еще перегрузку строковых литералов - всякие ByteString, Text и т.п. можно будет юзать без pack'ов. Просто подставляя строку в кавычках куда надо.
                  Ответить
                  • Это как и для чего нужно? :-[
                    Ответить
                    • ByteString - бинарные данные, Text - текст. К.О.
                      Работают намного быстрее списка из чаров\байтов. Ну и набор сверток, мапов и прочего к ним есть, который оптимизнут, и умеет в fusion.

                      P.S. Есть ленивый ByteString и строгий ByteString.
                      P.P.S. И без перегрузки строковых литералов нужно писать ByteString.pack "хуй", а с перегрузкой просто "хуй", и он сам сделает все что нужно.
                      Ответить
                      • А как включить эту перегрузку? И как он догадается, где использовать обычные списки, а где ByteString?
                        Ответить
                        • А так же как с числовыми литералами. Числовой литерал 5 это, емнип, на самом деле fromInteger 5, а 1.4 это fromRational 1.4. Со строками вроде бы тоже самое, но я не помню названия функции.
                          Ответить
                      • А кроме ноуМономорфизм и перегрузок что посоветуете включать? Мне понравились параллельные генераторы списков, forall, возможность указания сигнатур по месту и типов выражений (если нужно, найду и впишу суда ключики). Что ещё посоветуете?
                        Ответить
                        • Параллельные генераторы это что?
                          Ответить
                          • http://www.haskell.org/ghc/docs/5.00/set/parallel-list-comprehensions.html
                            Ответить
                            • [ (x, y) | x <- xs | y <- ys ]


                              Это же тоже самое что:
                              [ (x, y) | (x, y) <- zip xs ys ]
                              Ответить
                              • Да, именно это по ссылке и написано.
                                Ответить
                                • Тогда ничего сверх-полезного в них нет.
                                  Ответить
                                  • В синтаксическом сахаре никогда не бывает чего-то сверхполезного. Просто небольшое удобство в некоторых случаях.
                                    Ответить
                                    • Мне кажется разворачивание кортежа + zip удобнее и, главное, очевидне.
                                      Ответить
          • > написать сигнатуру перед написанием функции
            > а затем по-желанию убрать.
            Регулярно так делал (вне хаскеля конечно). Много раз об этом жалел, если приходилось править безсигнатурные функции, тк чтобы разобраться - приходилось возвращать сигнатуры обратно. Но это так сказать нарушало красоту кода и я их убирал обратно, потом снова возвращал и снова убирал и так несколько раз.
            Ответить
            • > нарушало красоту кода

              Тут дело привычки. Мне больше нравится если есть сигнатура.

              Обычно сигнатуры и имени функции достаточно, чтобы полностью понять, что она делает.
              Ответить
    • Маленькие дети, ни за что на свете
      Не пытайтесь код на Хацкиле писать!
      В Хацкиле кортежи, в Хацкиле монады,
      А еще там жесткие, злые лямбды.

      Вам будут мозги рвать и убивать,
      Не пытайтесь, дети на хацкиле писать.

      Хацкил он статичный, Хацкил он урод
      В Хацкиле ужасный типа "чистый" код.
      Его форсят злодеи чтоб извращать детей -
      Ленивый, нехороший - трогать его не смей!

      И папочка и мамочка на говнокодике сидят,
      И папочка и мамочка деткам говорят:
      "Хацкил ужасен, да-да-да!
      Хацкил опасен, да-да-да!
      Хацкил ужасен, да-да-да!
      Хацкил опасен, да-да-да!
      Не учите Хацкиля, не пишите в Хацкиле,
      Не учите Хацкиля, не пишите в Хацкиле,
      Не учите Хацкиля, дети, никогда!"
      Ответить
    • Но папочка и мамочка уснули вечерком,
      А Гумно и fai - GHC уже читают,
      Хацкилем всех донимают,
      Паттерн-матчинг постигают,
      Ну и Хацкиль!
      Вот так Хацкиль!

      Типы нам не надо кодить
      - он и сам их повыводит
      Ну и Хацкиль!
      Вот так Хацкиль!

      Генератор списков оседлали
      ProjectEuler погоняли
      Ну и Хацкиль!
      Вот так Хацкиль!

      "Вон побочные эффекты
      Распахнули злую пасть.
      Сможете, вы, детки
      на грабли не наступать?"

      "Нам побочные эффекты
      Нипочём, нипочём,
      Мы побочные эффекты
      Монаднём, Монаднём"
      Ответить
      • Один стих краше другого. :)
        Ответить
      • Стихи понравились, но ты действительно считаешь, что на говнокод нельзя постить хаскель?
        Ответить
        • >что на говнокод нельзя постить хаскель?
          Нет. Ведь это код
          На говнокод, по-моему, можно постить вообще всё что угодно.
          Ответить
    • "Я краткий,
      Я понятный,
      Я простой и я функциональный!
      И мне не надо
      Ни паттернизма,
      Ни оопизма,
      Я только хочу маленьких
      (Да, очень маленьких!)
      маленьких, коротеньких функций побыстрей!"

      Он простотой своей прельщает,
      Он параллелит каждый бит,
      Он мусор сам весь собирает,
      И слово страшное кричит:
      "Крестоблядь, крестоблядь
      Перестань говно писать"

      А Гумно и fai смеются,
      Не нарадуются:
      "Ну и Хацкиль,
      Что за Хацкиль -
      Замечательный!"
      Ответить
      • Браво!
        Ответить
      • Снимаю перед вами шляпу! Отличные стихи!
        Ответить
        • На цитаты можно разбирать:

          "Крестоблядь, крестоблядь
          Перестань говно писать"

          "Посмотри-ка побыстрей
          Кто с на помощь к нам пришел!
          Ужас всех крестоблядей
          Добрый кодер ТарасБ!"
          Ответить
    • Не стерпел такой обиды С++,
      Убежал он на геймдев и ревёт,
      И Пушкова, и Пушкова
      Обратным вызовом зовёт.

      "Выходи-ка, поскорей!
      Этих гадких детей
      Корми калом побыстрей
      И говна ты не жалей!"

      Гумно с фаем задрожали -
      Как Пушкова увидали.
      Начали они бежать
      Но Пушкову их догнать

      Не составило трудов
      Хацкиль ведь не может
      Убегать быстрей крестов
      И многопоточность тоже...

      Но тут Гумно увидел:
      "Посмотри-ка побыстрей
      Кто с на помощь к нам пришел!
      Ужас всех крестоблядей
      Добрый кодер ТарасБ!"

      Добрый кодер ТарасБ
      К Гумну с faiем подбегает,
      И крестозлодею,
      Улыбаясь, говорит:

      "Крестосударь, ну-ка
      Развяжите, отпустите
      Этих маленьких детей!
      И давайте побыстрей!"

      Но Пушков Тараса хватает
      В крестобан его бросает.
      Гумно плачет и рыдает,
      Пушкова он умоляет:

      "Пушков смилуйся над нами,
      Отпусти нас поскорей
      К нашей милой маме!
      Похлебать её борщей

      От неё мы убегать
      Никогда больше не будем
      А об императивном коде
      Мы тоже не забудем!"
      Ответить
    • Пушков кричит: "Не проси пощады"
      "Пристрелю вас как собак"
      А Гумно плачет: "Не надо
      Я у мамочки дурак"

      "Ну уж нет!!!"
      Рявкнул Пушков, но ненароком,
      Взяв крестовый пистолет,
      Выстрелил себе он в ногу!

      А в Гумна не смог попасть!
      fai с Гумном на Хацкиль сели
      Снова бросились бежать
      И кричат "Скорее, ходу"
      Так как Хацкиль туповат.
      Ну а вот по говнокоду
      Ровным строем пхпешники идут
      Песню звонкую поют
      (Вроде рифма, вроде складно
      А послушать - копипаста)
      Гумно с файем услыхали
      И на помощь их зовут.

      Те запыхавшись подбегают
      И ответ им свой дают
      "Маму с папой не слушались
      А над нами насмехались
      Что наши предки обезьяны
      И мы кодим за бананы"
      Ответить
      • Как-то нескладно, начало было более красивым...
        Ответить
        • та знаю. тогда просто было вдохновение и было весело писать, а сейчас высер какой-то получается.
          но, блин, не люблю неоконченные дела.
          Ответить
        • В общем по ходу дела пацаны встретили жаб, которые оказались мерзкими, питона, но он слишком медленно полз чтоб проглотить злодея, лисп, но тот оказался слишком ленивым чтобы им помочь.
          Потом Пушкофу надоело за ними гоняться, он подобрел и они всё вместе ушли с говнокода раковать на геймдев. Где и умерли от рака жопы.
          Ответить
          • > и они всё вместе ушли раковать на геймдев
            И жили долго и счастливо, и умерли атомарно.
            Ответить
            • А Тараса разбанили и отпустили после того как он не выдержал и сам начал писать на крестах.
              Ответить

    Добавить комментарий