Ответы пользователя по тегу Haskell
  • Как можно улучшить это решение задачи FizzBuzz?

    @AlexSku
    не буду отвечать из-за модератора
    использовать show и map
    Ответ написан
    Комментировать
  • В чём смысл такого вывода Char'ов?

    @AlexSku
    не буду отвечать из-за модератора
    1) Отображение - дело непростое. ФП предназначено для расчётов, а не для отображений. А именно: подаёте на вход функции параметры и получаете результат. Обычно под отображением понимают преобразование типа к строковому виду. В Haskell строка это список символов:
    type String = [Char]
    Если вы что-то делаете в интерпретаторе, то там ещё вычисления (и вывод) происходят в монаде IO.
    Для вывода многих типов есть функция show.

    2)
    как теперь вывести список чаров

    можете в интерпретаторе так и написать: ['a', 'b', 'c']
    Есть синтаксический сахар: список char можно выводить в виде строки, т.е. без скобок, но в двойных кавычках: "abc"
    если он отображается как список стрингов

    нет такого. Список char отображается в двух видах (см. выше), они равнозначны.
    почему список символов отображается как строка символов?

    Это синтаксический сахар, чтобы не писать запятые после каждого символа.
    Ответ написан
    Комментировать
  • Как понять каррирование в Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    1) Каррирование позволяет функции скармливать аргументы по-одному (несколько, не все сразу), т.е. возможно частичное применение.
    Напр., (+) x y имеет тип:
    a -> a -> a
    Чтобы понять, какая стрелка первая, пользуемся ассоциативностью (здесь правой):
    а -> (a -> a)
    Поэтому в Haskell все каррированные функции это функции одного аргумента. Формально сложение, это функция, принимающая один аргумент (типа а) и выдающая функцию (типа a -> a). Но это философия. Для удобства и скобки можно не писать, и предоставить (если нужно) плюсу два аргумента (тогда результатом будет число).
    2) В формальном подходе map тоже функция одного аргумента:
    (a -> b) -> ([a] -> [b])
    (это классическое определение функтора по теории категорий).
    Но благодаря каррированию, можно также представить map как функцию (высшего порядка, т.к. первый аргумент - функция) принимающую два аргумента: функцию и список. Результат - список.
    Первый аргумент типа (a -> b), второй типа [a].
    3) там, где :: , пишутся типы аргументов и результата. Сами аргументы и тело функции (выражение) пишутся ниже через =.
    (при этом может быть применён бесточечный стиль, когда не все аргументы перечислены, напр.:
    mysum = (+)
    или mysum x = (+) x
    или mysum x y = (+) x y -- здесь все аргументы)
    Ответ написан
    Комментировать
  • Как понять каррирование и частичное применение функции? В чём их различия?

    @AlexSku
    не буду отвечать из-за модератора
    1) скобки в описании типа расставляются вправо, так что может быть любое количество аргументов:
    fun:: a -> (a -> (a -> a))
    2) частичное применение означает, что функции можно скармливать аргументы по одному в любом количестве.
    (в режиме оператора можно подсунуть второй, а первый - потом).
    3) про каррирование. Есть вид передачи параметров в других языках fun(p1, p2, p3). На Haskell это передача одной группы (кортежа). Есть функции высшего порядка curry и uncurry, которые вашу функцию переводят в противоположный тип.
    Ответ написан
    Комментировать
  • Кто такие Альтернативные функторы?

    @AlexSku
    не буду отвечать из-за модератора
    Если плясать от операции объединения моноида (<>), то для чисел сделаны два newtype Sum и Product, то бишь сумма и произведение. Вот для монад списка Monad это произведение
    [(a,b) | a <- [1,2], b <- [3,4] ] -- будет [(1,3),(1,4),(2,3),(2,4)] (генератор списка это синтак. сахар для монады)
    т.е. перебор каждого с каждым, а для MonadPlus это сложение (соединение)
    [1,2] <|> [3,4] -- будет [1,2,3,4]
    Alternative же это то же, что и MonadPlus, просто MonadPlus появился раньше.
    Кстати Applicative (от которого идут монады) тоже имеет оператор произведения:
    (,) <$> [1,2] <*> [3,4] -- будет [(1,3),(1,4),(2,3),(2,4)]

    Alternative для Maybe реализует newtype First, т.е. первый "ненулевой" элемент (если есть).

    Применяется в парсерах. Напр., если надо чтобы строка начиналась с буквы или цифры, запускаете два парсера через <|>.
    Посмотреть можно на Степике, 2-я часть Haskell, уроки про парсеры (урок 1) и Alternative / MonadPlus (урок 2.5)
    Ответ написан
    1 комментарий
  • Как сделать проверку гипотезы Гольдбаха на Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    Повтор от предыдущего вопроса:

    Тут всё понятно:
    Гипотеза: любое чётное (>2) представимо как сумма двух простых.
    Берём список нечётных (простые всегда нечётные, кроме 2): [ 3, 5 ..]. Это будет первым слагаемым. Если искомое число a, то второе слагаемое a-c (c - первое слагаемое). Ясно, что список первого слагаемого можно ограничить a `div` 2, т.е. получаем [3,5..a `div` 2].
    Дальше фунция map, получая каждый элемент списка (c) формирует пару слагаемых: с - первое, a-c - второе.
    Это мы описали map (\c -> (c, a - c)) [3,5..a `div` 2]
    Напр., для 10 получим список [(3,7), (5,5)].

    Из этого списка надо выкинуть пары, где есть непростые (составные) числа. Напр., для 12 список [(3,9), (5,7)] первая пара выкинется (фильтром), т.к. 9 - составное (делится на 3).
    Если в результирующем списке несколько пар, то func1 просто берёт первую (напр., для 10 будет пара (3,7)). func1 это стандартная функция head.
    Ну и вспомогательные функции: isPr - проверка на простое число, isFactor - на составное.
    Ответ написан
    Комментировать
  • Как работает этот код на хаскеле?

    @AlexSku
    не буду отвечать из-за модератора
    А вот если пользоваться библиотеками, то, подключив два модуля, можно сделать коротко:
    Prelude Data.List.Split Data.List> n = 2
    Prelude Data.List.Split Data.List> intercalate "@" $ chunksOf n "1234567"
    "12@34@56@7"
    Ответ написан
  • Какой фактический размер у типа Int на платформе GHC, Windows 64?

    @AlexSku
    не буду отвечать из-за модератора
    У меня maxBound ::Int чётко 2^31 (т.е 4 байта, старший бит - знак)
    Ответ написан
    1 комментарий
  • Как решить задачу о быках, коровах и телятах на Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    Один из вариантов (простенький, но не оптимальный) такой:
    Prelude> [(bull, cow, calf) | bull<-[1..10], cow<-[1..20],calf<-[1..200], bull + cow + calf == 100, 10*bull + 5*cow +calf/2 == 100]
    [(1.0,9.0,90.0)]
    Ответ написан
    Комментировать
  • Как вызвать функцию для всех элементов списка в Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    Всё верно:
    Prelude> myFun = map (^2)
    Prelude> myFun [1, 2, 3, 4]
    [1,4,9,16]
    Ответ написан
    Комментировать
  • Насколько востребованны функциональные языки программирования, и почему их мало используют в коммерческой разработке?

    @AlexSku
    не буду отвечать из-за модератора
    Если не боитесь мат. абстракций (функторы, монады...), то - вперёд. Мало кто может этим пользоваться, поэтому можно попытаться заработать хорошо, при этом ваш код будет лаконичным, но кроме математиков его никто не поймёт.
    Ответ написан
    9 комментариев
  • Как работает композиция в Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    1) y = show x
    где х - число. Результат y - строка
    2) z = map digitToInt y
    digitToInt переводит все символы (разряды исходного числа x в числа). Результат z - список чисел.
    Т.е. x = 125, y = "125" или ['1', '2', '5'], z = [1, 2, 5]
    3) sum z считает сумму списка, в нашем случае сумму цифр исходного многоразрядного числа.

    Ответ на последний вопрос такой. У функции самый большой приоритет (10), поэтому map "притягивает" аргумент digitToInt. У ОПЕРАТОРА композиции приоритет, вроде, 9. Поэтому последний пример эквивалентен исходному и скобки не обязательны. Правда, советуют ставить пробелы вокруг точки (оператора композиции) для наглядности.
    Ответ написан
  • Функции для работы со строкой на Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    Не знаю, как с русским, но первая функция (потом вы назвали её второй) это фильтр:
    import Data.Char
    f1 = filter isAlpha    -- или isLetter
    
    > f1 "a,b,c"
    > "abc"
    Ответ написан
  • На Haskell можно задать систему уравнений, чтобы он сам ее решил? А не писать функции для решения самостоятельно?

    @AlexSku
    не буду отвечать из-за модератора
    Пролога не знаю, но функциональный стиль действительно декларативный. Напр. x = x +1 в императивном означает сложить значение x с единицей и положить результат в x.
    В ФП это будет рекурсивный вызов функции x.
    По поводу решения. Напр., в Матлабе эта система записывается как A*x = b, где А - матрица 2х2, x - вектор 2х1 неизвестных (x и y), а b - вектор 2х1 левой части. Решение находится в виде левого деления: x = A \ b.
    На Хаскеле надо бы описать тип данных "матрица" и оператора "левое деление" (можно методом треугольника) и тогда - вуаля, всё получится.
    Ответ написан
  • Как упростить логическое выражение?

    @AlexSku
    не буду отвечать из-за модератора
    можно так:
    simplifyExpr (Not (Not p)) = simplifyExpr p -- рекурсивный вызов
    -- другие шаблоны
    
    -- конец рекурсии
    simplifyExpr p = p
    
    -- проверка
    >simplifyExpr (Not (Not (Var "abc")))
    Var "abc"
    Ответ написан
  • Для чего используется Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    Есть интересные лекции по функциональному программированию Дмитрия Сошникова (правда, в основном, на F#).
    Допустим, видишь x = 2+3.
    Можно сказать: подсчитай выражение и результат положи в ячейку x.
    А функциональный программист скажет: вы описали (метод расчёта) функцию х (т.е. у вас не команды, а определение функции). Из кучи определений компилятор постарается найти сокращённый вариант, который будет решением при подстановке данных.
    Ответ написан
    1 комментарий
  • Как понять как работает эта функция в Haskell?

    @AlexSku
    не буду отвечать из-за модератора
    Если последний аргумент встречается справа тоже на последнем месте, то их можно не писать. Это называется бесточечным стилем.
    fun x y z = (...) z
    и fun x y = (...)
    это одно и тоже.
    Ответ написан
    3 комментария
  • Какие книги почитать по функциональному программированию?

    @AlexSku
    не буду отвечать из-за модератора
    Есть курс Дмитрия Сошникова на Интуите. Хотя он голосует за F#, но мне больше понравился Haskell.
    Ответ написан
    Комментировать
  • Есть ли уроки haskell под windows?

    @AlexSku
    не буду отвечать из-за модератора
    stepik, 2 курса
    Ответ написан
    Комментировать