Ответы пользователя по тегу Haskell
  • Существует ли простой и элегантный способ добавить информацию о позиции в синтаксическое дерево с взаимно-рекурсивными типами?

    Вроде такого способа нет.

    А почему второй вариант неудобен?
    См, например, haskell-src-exts, там у каждого типа есть доп. элемент типа l, в котором может быть позиция или что-то ещё.
    В ghc сделано аналогично, но чуть иначе - некоторые конструкторы обёрнуты в Located
    Ответ написан
  • Что должна уметь IDE для haskell?

    А в каком контексте вопрос? Всё как обычно, вроде

    1. подсвечивать ошибки (по сохранении файла или прямо во время написания кода)
    2. показывать типы (выведенные и/или из определения символа)
    3. показывать доки (в том числе и в исходниках написанные)
    4. запускать интерпретатор на проекте
    5. отладчик
    6. переименования
    7. вынос локального определения

    и т.п.
    Ответ написан
    Комментировать
  • Копируется ли состояние при каждой операции над монадой состояния в Haskell?

    Копируется, только надо учитывать ленивость и чистоту Хаскеля.
    Если взять обычный список и класть ему в голову - ничего не надо будет копировать, так как добавление головы не требует копирования хвоста, новый список будет просто ссылаться на хвост. Удаление головы (т.е. взятие хвоста) тоже не требует создавать копий.
    Если же вы будете в качестве состояния использовать какой-либо строгий тип данных, да с unboxed членами, тот да, будет копироваться.
    Надо учитывать так же и другую вещь: накопление thunk'ов. Например, если состояние - это число, и вы миллион раз сделаете modify (+1), по факту там будет лежать отложенное вычисление на миллион прибавлений единиц, что будет кушать память. Потому есть строгая монада state, а также modify', который форсирует применение переданной функции.
    Ответ написан
    Комментировать
  • Почему cabal test считает все тесты пройденными?

    Выше ответили, я прокомментирую. main должна иметь тип IO t, где t — любой тип, результат будет проигнорирован. Чтобы вернуть exitcode отличный от нуля, надо пользоваться соответствующими функциями: exitWith, exitFailure и прочими. Судя по всему, HUnit этого автоматически не делает, возвращая лишь статистику, которая игнорируется.
    Посему вам надо написать функцию, которая вызовет exitFailure сама, если errors или failures в Counts больше нуля.
    Ответ написан
  • Как запустить код написанный на Haskell из под Java проекта?

    1) Через C. Haskell экспортит свои функции (foreign export), из Java их зовём (на Java не писал, так что не знаю, как там принято). С тех пор, как я собирал dll под windows прошло много времени, раньше это было несколько напряжно (именно под windows), сейчас возможно и проблемы нет. Почитать можно тут: https://wiki.haskell.org/Calling_Haskell_from_C https://downloads.haskell.org/~ghc/latest/docs/htm...
    2) Через сокеты. Запускаете Haskell-процесс, который слушает подключение. Далее кормите его запросами, а он выдает ответы. В каком виде запросы - неважно, JSON, например.
    Ответ написан
    Комментировать
  • Какой ФП язык выучить?

    Если в академических, то, как ответили выше, учите Haskell, а лучше [сразу или потом] Agda2 с зависимыми типами, узнаете много нового.
    Ответ написан
    Комментировать
  • Что такое список в функциональных языках программирования?

    Отвечу за Haskell.
    Вот список:
    data [a] = [] | a : [a]
    Т.е. список либо пуст, либо имеет [ссылку на] [недовычисленную] голову и [ссылку на] [недовычисленный] другой список - хвост. Т.о. чтобы пробежаться по списку (без использования готовых функций), надо проверять, не является ли он пустым, если нет, работать с головой, а хвост обрабатывать рекурсивно.
    Список иммутабельный, т.е. ничего никуда вставить нельзя, однако списки могут "шарить" общий хвост, например:
    list1 = [2,3,4]
    list2 = 1 : 2 : list1
    list3 = 0 : 0 : list1

    В памяти будет (после форсирования, рассмотрение ленивости я опускаю) как-то так:
    1-2
       \
        2-3-4
       /
    0-0
    Ответ написан
    Комментировать
  • Как рекурсивно распарсить скобки?

    Во-первых, заменим splitOn " " на words, который съест все пробелы. Далее, concat $ map ... - это то же, что и concatMap .... Рассмотрим sepBr. Он берёт строку без пробелов и делит её на куски, если там есть операторы, числа или скобки. Если строка уже пустая, результат - пустой список. Если строка непустая, то возможны варианты. Если первый её символ - какая-то скобка, отделяем эту скобку, а остальное делим опять при помощи sepBr. Иначе делаем так: разделим строку, чтобы сначала шли только цифры: span isDigit и посмотрим, что получилось. Если цифры есть - отделяем их, а остальное опять делим sepBr. Если цифр нет, то просто отделяем первый символ. Вот, что получилось:
    sep ∷ String → [String]
    sep = concatMap sepBr . words where
    	sepBr ∷ String → [String]
    	sepBr "" = [] -- нечего делить
    	sepBr s'@(x:xs)
    		| x `elem` "()" = [x] : sepBr xs -- скобка
    		| otherwise = case span isDigit s' of -- возьмём цифры
    			("", t:tl) → [t] : sepBr tl -- нет цифр, берём первый символ остатка
    			(n, tl) → n : sepBr tl -- есть цифры, их отдельно


    По поводу вашего второго варианта.
    if word == [] then [] else head word - т.е. a либо пустой список, либо символ, типы не совпадают. Но в вашем случае word не может быть пустым, ведь выше уже был паттерн sepBr "", так что можно просто оставить a = head word
    Далее, что такое ab? Это [a] ++ b, т.е. [head word] ++ init (tail word), т.е. это то же, что и просто init word. Аналогично bc = tail word. Вместо того, чтобы брать отдельно head и отдельно tail, можно воспользоваться паттерн-матчингом и записать (a : bc) = word.
    С учётом этого ваш вариант переписывается в
    sep2 ∷ String → [String]
    sep2 = concatMap sepBr . words where
    	sepBr ∷ String → [String]
    	sepBr ""  = []
    	sepBr " " = []
    	sepBr word
    		| a `elem` brackets = [[a]] ++ sepBr bc
    		| c `elem` brackets = sepBr ab ++ [[c]]
    		| otherwise = ([a : bc])
    		where
    			(a : bc) = word
    			c = last word
    			ab = init word
    			brackets = ['(', ')']

    И он вполне работает.
    Ответ написан
    1 комментарий
  • Как порядок вычисления выражений в этом коде?

    movieValue .: "id" создает парсер, читающий id. Применённый к нему Movie <$> создаёт парсер, который к id применит конструктор Movie, в итоге результатом такого парсера будет функция от одного недостающего аргумента.
    Также movieValue .: "title" создаёт парсер, читающий title.
    Если б это были просто функция и значение, можно было бы одно к другому применить, в нашем случае используют <*>, который создаст парсер, комбинирующий оба переданных ему парсера, применяя результат одного к результату другого. При этом так как оба парсера независимы, можно их выполнять в любом порядке. Но в данном случае слева направо. Проверить можно так:
    parseEither (\(Object v) -> (,) <$> v .: "a" <*> v .: "b") (object [])

    Ответ:
    Left "key \"a\" not present"
    Если бы он сначала вычислял правый аргумент, ошибка была бы другая - не найден b.

    А что вы имеете в виду под порядком вычисления?
    head <$> o .: "movies"
    Хаскель ленивый язык, пока не понадобится, не вычисляет. В этой строке вы, считай, thunk создали, который, когда его дёрнут, начнёт что-то там вычислять. В этом примере, когда дёрнут, начнёт вычислять, а не фейлится ли парсер, для чего придётся убедиться, что не фейлятся входящие в него парсеры. Порядок может быть любой, но автор библиотеки скорее всего сделал порядок естественным.
    Ответ написан
    7 комментариев
  • Почему ghc: could not execute: hsx2hs?

    hsx2hs в PATH прописан?
    Ответ написан
    Комментировать
  • Нужно ли знать математику, чтобы программировать на haskell?

    Не нужно. Более того, я лично считаю, что если человек ещё не изменил свой мозг работой с императивными языками, то изучить Haskell ему будет проще, чем большинство других мейнстримовых языков, и вся сложность возникает именно из-за необходимости перестроить мышление, но масштабных экспериментов я не проводил.
    Вот для Agda матан желательно :)
    Ответ написан
    Комментировать
  • Как создать композицию функции на саму себя?

    Функция применяется n + 1 раз к n. Для этого надо список из n + 1 функций f свернуть при помощи композиции, а затем применить к аргументу. Добавим ещё fromIntegral, так как в примерах у вас синусы, которым нужно число с плавающей точкой, а n же у вас - целое (функцию можно применить только целое кол-во раз).

    execute f n = foldr1 (.) (replicate (succ n) f) (fromIntegral n)


    где replicate (succ n) f - список из n + 1 функций f, foldr1 (.) - свёртка списка композицией

    Есть и второй вариант, не сворачивать n + 1 функций f через композицию, а сворачивать список, на каждом шаге сразу применяя к аргументу, т.е. так:

    execute f n = foldr ($) (fromIntegral n) (replicate (succ n) f)


    где ($) - функция применения, т.е. f $ x = f x
    Ответ написан
    Комментировать
  • В чем отличие промисов от монад?

    Promise - одна из монад, где bind (>>=), упрощённо, из обещания и из последующей функции делает новое обещание, которое дожидается выполнения первого обещания и передаёт результат в следующую функцию. В итоге управление в вызывающую функцию возвращается на первом же ожидании.

    Но монады есть и другие. Например Either, позволяющий выдать "ошибку", т.о. обрывая всю цепь вычислений на первой же ошибке. Или Maybe, ведущий себя аналогично Either, но не с возвратом какого-то ошибочного значения, а просто с остановкой на первом фейле. Список - тоже монада, там последующая функция будет вычислена на каждом элементе, а результате сконкатенированы.
    Ответ написан
    Комментировать
  • Как в Haskell использовать сопоставление с образцом в охранных выражениях (в конкретном примере)?

    Сопоставление с образцом можно использовать, но в guard'ах надо явно указывать, что сопоставляем, т.е. в данном случае аргумент - list

    foo :: Eq a ⇒ [a] → Bool
    foo list
    	| [] ← list = True
    	| [x] ← list = True
    	| head list ≡ last list = foo . tail . init $ list
    	| otherwise = False


    Хотя лично я предпочитаю исходный вариант.
    Ответ написан
    Комментировать
  • Какая есть удобная IDE для Haskell по Ubuntu?

    Посмотрите на leskah, но я его не использую, поэтому понятия не имею, удобный ли он.
    Ответ написан
    Комментировать
  • Как научить cabal (менеджер пакетов в Haskell Platform) понимать кириллицу в путях?

    А на гитхабе не спрашивали?
    Какая версия cabal-install? Если та, что в Haskell Platform, то она довольно старая, надо сделать 'cabal install cabal-install' и проверить на последней.
    Тут не об этом ли?
    Ответ написан
    Комментировать