色々疲れたので現実逃避。
「関数プログラミングの楽しみ」という本がありまして。*1
- 作者: Jeremy Gibbons and Oege de Moor,山下伸夫
- 出版社/メーカー: オーム社
- 発売日: 2010/06/23
- メディア: 単行本(ソフトカバー)
- 購入: 3人 クリック: 90回
- この商品を含むブログ (17件) を見る
中身はHaskellなんですが、3章の「おりがみプログラミング」の(un)foldは再帰的な型があれば他の言語でも(やる意味はともかく)実装できます。
ところでAdaには配列というものがあります。*2
という訳で、どういう訳だか配列で(un)foldっぽいものを作ってみようと思い立ちました。
fold/unfoldそのものと、その便利な使い方については上の本を読んでください。
やる意味
なし
使い勝手
悪い
効率
悪い
特徴
- 無駄にgeneric使う
- 無駄にexpression functions使ってみる
ソースとか
origami.ads
仕様。無駄にgeneric。
pragma Ada_12; generic type Index_Type is (<>); type Element_Type is private; type Array_Type is array (Index_Type range <>) of Element_Type; package Origami is generic type Result_Type is private; function Fold_R (F : access function (E : Element_Type; SoFar : Result_Type) return Result_Type; I : Result_Type; S : Array_Type) return Result_Type; generic type Input_Type is private; with function "&"(Left, Right : Array_Type) return Array_Type is <>; function Unfold_R (End_Of_Input : access function (I : Input_Type) return Boolean; Element : access function (I : Input_Type) return Element_Type; Renew_Input : access function (I : Input_Type) return Input_Type; Input : Input_Type) return Array_Type; end Origami;
origami.adb
A'Length=0な配列Aの簡単な書き方が分からなくて右往左往。
pragma Ada_12; package body Origami is function Unfold_R (End_Of_Input : access function (I : Input_Type) return Boolean; Element : access function (I : Input_Type) return Element_Type; Renew_Input : access function (I : Input_Type) return Input_Type; Input : Input_Type) return Array_Type is (if End_Of_Input(Input) then (Index_Type'Succ(Index_Type'First)..Index_Type'First => <>) else Array_Type'(Index_Type'First=>Element(Input)) & Unfold_R(End_Of_Input, Element, Renew_Input, Renew_Input(Input))); function Fold_R(F : access function (E : Element_Type; SoFar : Result_Type) return Result_Type; I : Result_Type; S : Array_Type) return Result_Type is (if S'Length=0 then I else F(S(S'First), Fold_R(F, I, S(Index_Type'Succ(S'First) .. S'Last)))); end Origami;
テストしてみた
pragma Ada_12; with Ada.Text_Io; with Origami; procedure Origami_Test is type Nat_Arr is array(Positive range <>) of Natural; package O is new Origami (Index_Type => Positive, Element_Type => Natural, Array_Type => Nat_Arr); function Eq_0 (N : Natural) return Boolean is (N = 0); function Mod_2 (N : Natural) return Natural is (N mod 2); function Div_2 (N : Natural) return Natural is (N / 2); function G is new O.Unfold_R(Input_Type => Natural); A : Nat_Arr := G(Eq_0'Access, Mod_2'Access, Div_2'Access, Natural'Value(Ada.Text_Io.Get_Line)); function F is new O.Fold_R(Result_Type => Natural); function Mul (E : Natural; SoFar : Natural) return Natural is (SoFar*2+E); begin for E of reverse A loop Ada.Text_Io.Put(E'Img); end loop; Ada.Text_Io.New_Line; Ada.Text_Io.Put_Line(Natural'Image(F(Mul'Access,0,A))); end Origami_Test;
なんとなく動いてる気がする
123456 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 123456
しかし実際無駄な。
あ、あとそろそろHaskellもちゃんとやりたい。