# 例: ファンクタを用いた有理数パッケージ

```typedef
intmod (a:t@ype) = '{
ofint= int -> a
, fprint= (FILEref, a) -> void
, neg= (a) -> a // negation
, sub= (a, a) -> a // subtraction
, mul= (a, a) -> a // multiplication
, div= (a, a) -> a // division
, mod= (a, a) -> a // modulo operation
, cmp= (a, a) -> int // comparison
} // end of [intmod]
```

```abst@ype rat (a:t@ype) = (a, a)

typedef
ratmod (a:t@ype) = '{
make= (a, a) -<cloref1> rat a
, fprint= (FILEref, rat a) -<cloref1> void
, numer= rat a -> a // numerator
, denom= rat a -> a // denominator
, neg= (rat a) -<cloref1> rat a // negation
, sub= (rat a, rat a) -<cloref1> rat a // subtraction
, mul= (rat a, rat a) -<cloref1> rat a // multiplication
, div= (rat a, rat a) -<cloref1> rat a // division
, cmp= (rat a, rat a) -<cloref1> int // comparison
} // end of [ratmod]
```

```fun{a:t@ype}
ratmod_make_intmod (int: intmod a): ratmod a
```

```staload M = "libc/SATS/math.sats"

val ratmod_int = let
//
val intmod_int = '{
ofint= lam (i) => i
, fprint= lam (out, x) => \$extfcall (void, "fprintf", out, "%i", x)
, neg= lam (x) => ~x
, add= lam (x, y) => x + y
, sub= lam (x, y) => x - y
, mul= lam (x, y) => x * y
, div= lam (x, y) => x / y
, mod= lam (x, y) => op mod (x, y)
, cmp= lam (x, y) => compare (x, y)
} : intmod (int) // end of [val]
//
in
ratmod_make_intmod<int> (intmod_int)
end // end of [val]

val ratmod_dbl = let
//
val intmod_dbl = '{
ofint= lam (i) => g0i2f(i)
, fprint= lam (out, x) => \$extfcall (void, "fprintf", out, "%0.f", x)
, neg= lam (x) => ~x
, add= lam (x, y) => x + y
, sub= lam (x, y) => x - y
, mul= lam (x, y) => x * y
, div= lam (x, y) => \$M.trunc (x / y) // truncation
, mod= lam (x, y) => \$M.fmod (x, y)
, cmp= lam (x, y) => compare (x, y)
} : intmod (double) // end of [val]
//
in
ratmod_make_intmod<double> (intmod_dbl)
end // end of [ratmod_dbl]
```

ratmod_make_intmod 関数の実装は オンライン から入手できます。 また関連したテストコードも オンライン から入手できます。