۱۳ - ۳کار با یه پروژهی پایه
یادگیریِ Cabal و Stack رو با ساخت ِ یه پروژهی نمونه به اسمِ hello شروع میکنیم. برای اینکه حجمِ کارمون رو کَم کنیم، با git پروژهی نمونه رو clone میکنیم. به آدرسی که پروژههاتون رو ذخیره میکنین برین و آدرسِ مخزن ِ https://github.com/haskellbook/hello رو git clone کنین.
ساخت ِ پروژه
برین به پوشهای که دستورِ git clone درست کرد.
$ cd helloمیتونین فایلِ hello.cabal رو ویرایش کنین. مثلاً میتونین بجای “Your Name Here” اسمتون رو بنویسین. بعدش پروژه رو بسازین:
$ stack buildاگه گیر داد که GHC باید نصب شده باشه، نترسین! یکی از مزایای Stack اینه که میتونه GHC هم براتون مدیریت کنه. قبل از اینکه دوباره stack build رو امتحان کنین، این کار رو بکنین:
$ stack setupدستور setup برای Stack، براساس اسنپشات ِ LTS که در فایلِ stack.yaml ِ پروژهتون تعیین شده، نسخهی GHC ِ موردِ نیازتون رو تشخیص میده. فایلِ stack.yaml برای تشخیصِ نسخهی پکیجها و پیدا کردنِ نسخهای از GHC که اونها بهتر باهاش کار میکنن استفاده میشه. اگه این کار لازمتون نشد، احتمالاً نسخهی GHC که داشتین سازگار بوده، یا شاید setup رو قبلاً برای یه اسنپشات ِ LTS ِ دیگه که همین نسخهی GHC رو لازم داشته اجرا کرده بودین. از سایتِ Stackage میتونین بیشتر یاد بگیرین.
بارگذاری و اجرای کُد از REPL
بعد از کارهای بالا، REPL رو اجرا میکنیم.
$ stack ghci
[... یه کم سروصدا ...]
Ok, modules loaded: Main.
Prelude> :l Main
[1 of 1] Compiling Main
Ok, modules loaded: Main.
Preldue> main
hello worldاینجا با موفقیت GHCi REPL رو (واقف به پروژهمون) شروع کردیم، ماژول ِ Main رو بارگذاری کردیم، و بعد هم تابعِ main رو اجرا کردیم. استفاده از GHCi ِ داخلِ Stack برای شروعِ یه REPL، نه تنها امکانِ کار با کُدهای پروژهمون رو میده، بلکه امکانِ استفاده از وابستگیهای پروژهمون رو هم فراهم میکنه. این رو بعداً بیشتر نشون میدیم.
stack exec
بالاتر که دستورِ build رو اجرا کردین، شاید چنین چیزی رو هم دیدین:
Linking .stack-work/dist/{...شلوغی...}/helloاین رو Stack موقعِ کامپایل کردنِ پروژه به یه باینریِ اجراشدنی و اتصال به اون میگه. برای اجرای اون فایلِ باینری میتونین کُلِ آدرسش که Stack گفت رو وارد کنین، اما راه سادهتر هم داره – exec! این دستورها رو از داخل پوشهی پروژهمون وارد کردیم:
$ hello
zsh: command not found: hello
$ stack exec -- hello
hello worldStack جای همه برنامههای اجراشدنی رو میدونه، پس با دستورِ exec از Stack لازم نیست کُلِ آدرسِ یه برنامه رو وارد کنین.
پاراگرافهای executable در فایلهای Cabal
بالاتر، Stack به خاطرِ این پاراگراف از فایلِ hello.cabal یه اجراشدنی درست کرد:
executable hello
-- [1]
hs-source-dirs: src
-- [2]
main-is: Main.hs
-- [3]
default-language: Haskell2010
-- [4]
build-depends: base >= 4.7 && < 5
-- [5]۱.
این اسمی که بعد از تعریفِ یه پاراگراف ِ executable اومده، به Stack یا Cabal میگه که چه اسمی برای باینری یا اجراشدنی ای که درست میکنه بذاره.
۲.
به این پاراگراف میگه که کجا دنبالِ کُدِ منبع بِگَرده – در این مورد، زیرپوشه ِ src.
۳.
اجرا ِ این باینری، اول از هر کاری دنبال یه تابعِ main داخل یه فایل به اسمِ Main با اسمِ ماژول ِ Main میگرده. دقت کنین که اسمِ ماژولها و فایلها باید یکی باشن. کامپایلری که استفاده میکنین (نه فقط Stack) فایلی که ماژول ِ Main نیست رو به عنوان نقطهی شروعِ اجرایِ برنامه نمیپذیره. به این هم توجه داشته باشین که همهی آدرسهایی که در hs-source-dirs نوشتین رو، به دنبالِ Main.hs میگَرده. اینجا فقط یه آدرس نوشتیم، پس src/Main.hs رو پیدا میکنه که تنها فایل منبع ِمون ِه.
۴.
نسخهای از استانداردِ هسکل که باید انتظار داشته باشه رو تعیین میکنه. نه جالبه، نه کارِ زیادی میکنه – بیشتر تکرارنوشت* ِه، اما واجبه.
م. لغت boilerplate در علم کامپیوتر برای قطعاتی از نوشته که همیشه لازم هستن و تغییری هم نمیکنن به کار میره. تکرارنوشت پیشنهاد بنده به عنوان لغت معادله.
۵.
این معمولاً بخشِ جوندارتر از هر پاراگراف ِ Cabal ِه (بین پاراگرافهای executable، library، و test-suite). این مثال (base) واقعاً حداقلِ وابستگی تو هر پروژهی هسکله، بدونِ کتابخونه ِ base تقریباً هیچ کاری نمیشه کرد. بعداً اضافه و نصب کردن وابستگیهای بیشتر رو نشون میدیم.
یه نکته در مورد اجراشدنیها و کتابخونهها
پروژهی ما فقط شاملِ یه پاراگراف ِ executable ِه، که برای یه برنامهای که فقط در ترمینال اجرا و استفاده میشه (command-line application) کفایت میکنه. زمانهایی که کُدِ ما قراره برای پروژههای بقیه هم قابل استفاده باشه، باید در یه پاراگراف ِ library داخلِ فایلِ .cabal مشخص کنیم که میخوایم کدوم ماژولها افشا بشن. اجراشدنیها، برنامههایی هستن که سیستم عامل مستقیماً اجراشون میکنه، اما کتابخونهها کُدهایی هستن که کامپایلر برای ساخت ِ سایرِ کتابخونهها و برنامهها ازشون استفاده میکنه.