Повторное использование кода Haskell в нескольких проектах

Я написал несколько модулей, которые часто хочу скопировать в другие проекты, чтобы повторно использовать код. Однако, если я просто скопирую модули, то, если я когда-нибудь захочу их улучшить, мне придется обновить все копии в различных репозиториях git для проектов, которые их используют.

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


person Mark Anastos    schedule 30.07.2017    source источник
comment
Что вы используете для создания кода? Стек или Кабал?   -  person arrowd    schedule 31.07.2017
comment
Вы можете сделать ссылки (если ваша файловая система поддерживает это) на файлы, чтобы обновление в одном месте означало, что оно обновлялось и в других местах.   -  person Willem Van Onsem    schedule 31.07.2017
comment
@arrowd Cabal, хотя это может измениться, я думаю   -  person Mark Anastos    schedule 31.07.2017
comment
@WillemVanOnsem Я думаю, но это все равно потребует внесения изменений в каждый репозиторий, что не идеально (хотя, возможно, неизбежно, я не знаю).   -  person Mark Anastos    schedule 31.07.2017
comment
В случае Cabal вы можете создавать песочницы Cabal и делать cabal sandbox add-source со всеми вашими библиотеками.   -  person arrowd    schedule 31.07.2017
comment
Песочницы @arrowd в значительной степени устарели с появлением сборки в стиле Nix. Я бы не беспокоился, изучая их как новичок; даже глобальные установки в старом стиле обычно работают нормально.   -  person leftaroundabout    schedule 31.07.2017


Ответы (2)


Объединяйте модули в пакеты (или, возможно, создавайте пакеты с одним модулем). Если вы еще этого не сделали, прочитайте Cabal руководство пользователя. Каждый пакет, как и любой другой код, должен находиться под контролем версий (git, darcs и т. д.), хотя это, строго говоря, не обязательно для ваших нужд.

Допустим, у вас есть один такой пакет, foo, содержащий модули Common.Foo и Common.Foo.Types, то есть у вас есть папка, содержащая Common/Foo.hs и Common/Foo/Types.hs, и файл foo.cabal с exposed-modules: Common.Foo Common.Foo.Types.

Проекты, в которых вы хотите использовать Common.Foo, также должны быть пакетами клики и, помимо очевидного import Common.Foo в исходных файлах Haskell, должны иметь файл .cabal с build-depends: foo.

Затем, всякий раз, когда вы меняли модули пакета foo, вы можете просто ввести cabal install --force-reinstalls (из каталога foos). Это обновит локальный реестр пакетов, и когда вы затем cabal configure и cabal build создадите другой проект, используя foo, он получит доступ к изменениям.

Подумайте также о том, чтобы фактически опубликовать свой пакет на Hackage (конечно, не забудьте поставить ему ясное, описательное имя!), то вам даже не придется беспокоиться о получении исходного кода и компиляции при переключении на другую машину — cabal может сделать это за вас.


--force-reinstalls необходим только после того, как вы также install отредактировали один из пакетов, зависящих от foo. После переустановки foo вы должны также пересобрать их — это небольшой недостаток в том, как Cabal-install регистрирует установки. Это станет ненужным в будущем.

person leftaroundabout    schedule 30.07.2017
comment
Таким образом, зависимый пакет сможет найти foo, потому что он внесен в этот локальный реестр пакетов? - person Mark Anastos; 31.07.2017
comment
@SwiftsNamesake stack — отличный инструмент для обеспечения воспроизводимых сборок, но я никогда не видел особого смысла использовать его для локального взлома. Особенно cabal new-build в стиле Nix на самом деле не оставляет желать лучшего, чем мог бы заполнить стек, IMO. Тем не менее, если вы добавите ответ, посвященный тому, как это можно сделать с помощью Stack, это, безусловно, стоящее дополнение. - person leftaroundabout; 31.07.2017
comment
Что ж, по моему опыту гораздо проще добавлять локальные зависимости с помощью stack, поэтому я и подумал об этом. - person SwiftsNamesake; 31.07.2017
comment
Сделанный. Я все же посмотрю на new-build. - person SwiftsNamesake; 31.07.2017

В дополнение к отличному ответу @leftroundabout, есть еще один способ добавить локальные зависимости с помощью stack, добавив путь к вашему stack.yaml:

flags: {}
packages:
- '.'
- location: path/to/my/incredible/haskell/goodies
- location:
    git: url/to/my/fp/repository
    commit: [commit-hash]
  extra-dep: true
[etc., etc.]

Предполагая, что вы еще не слышали об этом инструменте (который по большей части решает печально известную проблему клики), я настоятельно рекомендую проверить его.

person SwiftsNamesake    schedule 31.07.2017