# 関数プログラミングと無限論理多項式(12)

### F# の例(2)

F# もコンストラクターを3個に削減しました。Seq.unfold (iterate に相当)を使っています。

```let Align0<'T> (xs: 'T list) (len: int) (z: 'T): 'T list =
[
for xd in xs do yield xd
for i in xs.Length .. len - 1 do yield z
]
let ZipWith0<'T, 'U> (z: 'T) (f: 'T -> 'T -> 'U) (xs: 'T list) (ys: 'T list): 'U list =
let xsx = Align0 xs (List.length ys) z
let ysx = Align0 ys (List.length xs) z
List.map2 f xsx ysx
let FoldL0<'T, 'U> (z: 'U) (f: 'U -> 'T -> 'U) (xs: 'T list): 'U =
let mutable a = z
for x in xs do
a <- f a x
a
let FoldR0<'T, 'U> (z: 'U) (f: 'U -> 'T -> 'U) (xs: 'T list): 'U =
FoldL0 z f (List.rev xs)
let EqualAndLess (x: int) (y: int): bool * bool =
(x = y, x < y)

type LongDecimal(numbers: int list) =
let mutable decimals_: int list = numbers
new() = LongDecimal([])
new(n: int) = LongDecimal([n])
member this.decimals = decimals_
static member CarryStep_ (carry_and_dec: int * LongDecimal) (x: int): int * LongDecimal =
let (carry, dec): int * LongDecimal = carry_and_dec
let newdec = new LongDecimal([(x + carry) % 10] @ dec.decimals)
((x + carry) / 10, newdec)
member this.Decimalize (c: int, leave: bool): LongDecimal =
let (carry, dec) = FoldR0 (c, new LongDecimal()) LongDecimal.CarryStep_ this.decimals
if leave && carry <> 0 then
dec + carry * 10
else
dec
member this.Shift (e: int): LongDecimal =
(new LongDecimal([ for i in 1 .. e -> 0 ] @ this.decimals))
member this.CollectShiftMult (y: LongDecimal): LongDecimal list =
[
let mutable e: int = 0
for xd in this.decimals do
yield (y * xd).Shift(e)
e <- e + 1
]
static member (+) (x: LongDecimal, n: int): LongDecimal =
new LongDecimal([(List.head x.decimals) + n] @ List.skip 1 x.decimals)
static member (+) (x: LongDecimal, y: LongDecimal): LongDecimal =
(new LongDecimal(ZipWith0 0 (fun a b -> a + b) x.decimals y.decimals)).Decimalize(0, true)
static member (-) (x: LongDecimal, y: LongDecimal): LongDecimal =
let yds = Align0 y.decimals (List.length x.decimals) 0
(new LongDecimal(ZipWith0 0 (fun a b -> a + b) x.decimals (List.map (fun a -> 9 - a) yds))).Decimalize(1, false)
static member (*) (x: LongDecimal, xd: int): LongDecimal =
new LongDecimal(List.map (fun (yd: int) -> xd * yd) x.decimals)
static member (*) (x: LongDecimal, y: LongDecimal): LongDecimal =
List.fold (fun a b -> a + b) (new LongDecimal()) (x.CollectShiftMult y)
static member LessOrEqual (x: LongDecimal, y: LongDecimal): bool =
let equal = List.forall (fun b -> b) (ZipWith0<int, bool> 0 (fun a b -> a = b) x.decimals y.decimals)
if equal then
false
else
let get_not_eq (eq, lt) = not eq
let (eq, lt) = List.find get_not_eq (ZipWith0 0 EqualAndLess x.decimals y.decimals)
lt
member this.Print() =
let mutable res: string = "";
let mutable count: int = 0;
for d in this.decimals do
if count = 1 then
res <- res + "."
res <- res + d.ToString();
count <- count + 1
res

type Numbers(number: LongDecimal, square_difference: LongDecimal, scale: int) =
let mutable current_digit = 0
let mutable number: LongDecimal = number
let mutable square_difference: LongDecimal = square_difference
let mutable scale: int = scale
member this.CurrentDigit: int = current_digit
member this.GetNextDecimalDigit: int =
let two: LongDecimal = new LongDecimal(2)
current_digit <- -1
for dd = 9 downto 0 do
if current_digit < 0 then
let zd: LongDecimal = (new LongDecimal(dd)).Shift(scale)
let number_sq_diff: LongDecimal = number * zd * two + zd * zd
if LongDecimal.LessOrEqual (number_sq_diff, square_difference) then
number <- number + zd;
square_difference <- square_difference - number_sq_diff
scale <- scale + 1
current_digit <- dd
current_digit

type NumbersGenerator() =
let GenerateDecimal() =
let number: LongDecimal = new LongDecimal()
let square_difference: LongDecimal = new LongDecimal(3)
let nums: Numbers = new Numbers(number, square_difference, 0)
seq {
while true do yield nums.GetNextDecimalDigit
}
let generator = GenerateDecimal().GetEnumerator()
member this.GetNextDecimalDigit =
let b = generator.MoveNext()
generator.Current
member this.GenerateDecimal_() =
let number: LongDecimal = new LongDecimal()
let square_difference: LongDecimal = new LongDecimal(3)
let nums: Numbers = new Numbers(number, square_difference, 0)
seq {
while true do yield nums.GetNextDecimalDigit
}

let mutable current_numbers: Numbers = new Numbers(new LongDecimal(), new LongDecimal(), 0)
let GenerateDecimalServer() =
let number: LongDecimal = new LongDecimal()
let square_difference: LongDecimal = new LongDecimal(3)
current_numbers <- new Numbers(number, square_difference, 0)
seq {
while true do yield current_numbers
}
let generator_server = GenerateDecimalServer().GetEnumerator()
member this.GetNumbers: Numbers =
let b = generator_server.MoveNext()
generator_server.Current
member this.SetNumbers(numbers: Numbers): unit =
current_numbers <- numbers
member this.Numbers
with get(): Numbers =
this.GetNumbers
and set(value: Numbers) =
this.SetNumbers value
member this.GenerateDecimalServer_() =
let number: LongDecimal = new LongDecimal()
let square_difference: LongDecimal = new LongDecimal(3)
current_numbers <- new Numbers(number, square_difference, 0)
seq {
while true do yield current_numbers
}

let NextNumbers (numbers: Numbers): (Numbers * Numbers) option =
let n = numbers.GetNextDecimalDigit
Some (numbers, numbers)

type Calc() =
let mutable generator: NumbersGenerator = new NumbersGenerator()
let mutable result_number: LongDecimal = new LongDecimal()
let mutable count: int = 21

member this.RepeatGenerator(): string =
for e = 0 to count - 1 do
result_number <- result_number + (new LongDecimal(generator.GetNextDecimalDigit)).Shift(e)
result_number.Print()

member this.RepeatServer(): string =
for e = 0 to count - 1 do
let numbers: Numbers = generator_server.Numbers
let dd: int = numbers.GetNextDecimalDigit
generator_server.Numbers <- numbers
result_number <- result_number + (new LongDecimal(dd)).Shift(e)
result_number.Print()

member this.IterateGenerator(): string =
let list = Seq.toList (Seq.take (count) (generator.GenerateDecimal_()))
(new LongDecimal(list)).Print()

member this.IterateServer(): string =
let number: LongDecimal = new LongDecimal()
let square_difference: LongDecimal = new LongDecimal(3)
let init_numbers: Numbers = new Numbers(number, square_difference, 0)
let list = Seq.toList (Seq.take (count) (Seq.map (fun (numbers: Numbers) -> numbers.CurrentDigit) (Seq.unfold NextNumbers init_numbers)))
(new LongDecimal(list)).Print();

printfn "%s" ((new Calc()).RepeatGenerator())
printfn "%s" ((new Calc()).RepeatServer())
printfn "%s" ((new Calc()).IterateGenerator())
printfn "%s" ((new Calc()).IterateServer())
```

#### 実行結果

1.73205080756887729352
1.73205080756887729352
1.73205080756887729352
1.73205080756887729352