۱۳ - ۴تبدیل پروژه‌مون به کتابخونه

اول یه پاراگراف ِ ‏‎library‎‏ به فایلِ ‏‎hello.cabal‎‏ اضافه می‌کنیم:

library
  hs-source-dirs:      src
  exposed-modules:     Hello
  build-depends:       base >= 4.7 && < 5
  default-language:    Haskell2010

بعد هم یه فایل به آدرسِ ‏‎src/Hello.hs‎‏ می‌سازیم:

module Hello where

sayHello :: IO ()
sayHello = do
  putStrLn "hello world"

بعد از اون هم ماژول ِ ‏‎Main‎‏ رو تغییر میدیم تا از این تابعِ کتابخونه استفاده کنه:

module Main where

import Hello

main :: IO ()
main = do
  sayHello

حالا اگه بسازم‌ِش و بعد اجرا، کار می‌کنه.

$ stack build
$ stack exec hello
hello world

اما اگه می‌خواستیم یه آدرس جدا برای ‏‎exe‎‏ می‌داشتیم چطور؟

$ mkdir exe
$ mv src/Main.hs exe/Main.hs
- ^------------------------^
-     Main.hs م. انتقالِ

اونموقع باید فایلِ ‏‎.cabal‎‏ رو هم ویرایش کنیم تا بدونه ‏‎hello‎‏ از پوشه‌ی ‏‎exe‎‏ استفاده می‌کنه:

executable hello
  hs-source-dirs:      exe
  main-is:             Main.hs
  default-language:    Haskell2010
  build-depends:       base >= 4.7 && < 5

اگه سعی کنین این رو بسازین، نمیشه.

hello/exe/Main.hs:3:8:
Could not find module ‘Hello’
It is a member of the hidden package
  ‘hello-0.1.0.0@hello_IJIUuynUbgsHAquBKsAsb5’.
Perhapse you need to add ‘hello’ to the
  build-depends in your .cabal file.
Use -v to see a list of the files searched for.

دو راه داریم که این رو درست کنیم، یکی‌شون بهتر از اون یکیه. یه راه اینه که به آدرس‌هایی که ‏‎executable‎‏ جستجو می‌کنه ‏‎src‎‏ هم اضافه کنیم. اما پیشنهاد Cabal دقیقاً درسته. راه بهتر اینه که به حدومرزِ بینِ کتابخونه و اجراشدنی احترام بذاریم، و در عوض کتابخونه ِ خودمون رو به عنوان یکی از وابستگی‌ها اضافه کنیم:

executable hello
  hs-source-dirs:      exe
  main-is:             Main.hs
  default-language:    Haskell2010
  build-depends:       base >= 4.7 && < 5
                     , hello

با این تغییرات، ‏‎build‎‏ کار می‌کنه. تشخیصِ اینکه چه چیزهایی رو کتابخونه‌تون صادر یا افشا می‌کنه هم راحت‌تر میشه، که متعاقباً باعث میشه در صورتِ لزوم سریع‌تر اونها رو تغییر بدین.