![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
この文章では、プログラムを複数の Module に分割する方法について概説します。
一般に、ソースファイル1つにつき Module 1つを書き、Module 名とファイル名を一致させます。 [code 1] に例として Util.hs を示します。 Util.hs は Module Util を定義し、 3つの関数 (vpro, seqn, geozip) をエクスポートします。
[code 1]
01: --------------------- 02: -- utilities 03: -------------------- 04: module Util (vpro, seqn, geozip) where 05: 06: -- it calculates vector inner product 07: vpro :: [Double] -> [Double] -> Double 08: vpro ls1 ls2 = sum $ zipWith (*) ls1 ls2 09: 10: -- it calculates infinite sequence, 11: -- whose initial term and next-term-calculating-function are a0 and f 12: seqn :: a -> (a -> a) -> [a] 13: seqn a0 f = a0 : seqn (f a0) f 14: 15: -- 16: geozip :: [Double] -> [Double] -> [[Double]] 17: geozip ls0 ls1 = seqn ls0 (zipWith (*) ls1)
宣言 | インポートされる名前 | 参照の方法 |
---|---|---|
import Foo | hoge, bar | hoge, Foo.hoge, bar, Foo.bar |
import Foo () | (何もインポートされない) | |
import Foo (hoge) | hoge | hoge, Foo.hoge |
import qualified Foo () | (何もインポートされない) | |
import Foo hiding () | hoge, bar | hoge, Foo.hoge, bar, Foo.bar |
import Foo hiding (hoge) | bar | bar, Foo.bar |
import qualified Foo hiding () | hoge, bar | Foo.hoge, Foo.bar |
import qualified Foo hiding (hoge) | bar | Foo.bar |
import Foo as F | hoge, bar | hoge, F.hoge, bar, F.bar |
import Foo as F (hoge) | hoge | hoge, F.hoge |
import qualified Foo as F | hoge, bar | F.hoge, F.bar |
上に示したように、import にはいろいろなオプションがありますが qualified ... as がお勧めです。 qualified をつけると、インポートしたシンボルは必ず Module 名 (as を使って別名を定義したときは別名)で修飾しなければ ならなくなるので、名前空間が汚染されるのを防ぐことができます。
[code 2] は Module Util ([code 1]) をインポートしている Module です。Util の別名を U とし、 Util で定義された geozip は U.geozip として参照します(14, 20 行目)。
[code 2]
01: ------------------------------------------------ 02: -- This module makes matrix of S(x^i) 03: -- and vector [S(y), S(xy), S(x^2 y) ... S(x^n y)] 04: -------------------------------------------------- 05: 06: module MakeMat (make_sx, make_vxy) where 07: 08: import qualified Util as U 09: 10: -- making [[n, S(x), .. S(x^n)], [S(x) ... S(x^(n+1))], ... [S(x^n), ... S(x^2n)]] 11: make_sx :: Int -> [Double] -> [[Double]] 12: make_sx n xs = mat 0 13: where 14: lsum = map sum $ U.geozip (take (length xs) [1.0, 1.0 ..]) xs 15: mat i | i==n+1 = [] 16: | otherwise = (take (1+n) (drop i lsum)):(mat (i+1)) 17: 18: -- making [S(y), S(xy), S(x^2 y) ... S(x^n y)] 19: make_vxy :: Int -> [Double] -> [Double] -> [Double] 20: make_vxy n xs ys = map sum $ take (n+1) $ U.geozip ys xs
>ghc --make Main.hs -o lfit2.exeちなみに、lfit2 は前に取り上げた最小二乗法プログラムの改良版で、 パラメータの誤差を算出してくれます。
>lfit2 2 a.dat c0 = 2.531727598666521 (+-) 4.907248623738801e-2 c1 = -0.5005644499197217 (+-) 1.0695009355167438e-4 c2 = -2.9990377224373255e-2 (+-) 1.0217445932292105e-8
Haskell98 には他にもいろいろと書いてありますが、とりあえずここに書いてあることだけ 押えておけば十分だと思います。
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |