LoginSignup
2
0

More than 3 years have passed since last update.

Haskellを使いながら計算論 【2】自作自然数型とInteger型を対応させる

Last updated at Posted at 2021-04-15

前置き

この記事シリーズの目的は、

数学やプログラムを知ったかぶる著者が、『習うより慣れろ』の精神で、Haskellを使って計算論を学び、アウトプットしているうちに、いつの間にか計算論を理解しHaskell使いになっていることを目指す

ことで、
Haskellの実行環境構築や基本的な文法について詳細に解説すること、ではありません。

著者はHaskellや計算論のお勉強中なので、誤りなど、なんかよくないことを書いちゃっていたらご指摘いただけると幸いです。

シリーズ記事一覧はページの一番下に記載してあります。

今回の目的

次の2つのインスタンスを対応づける関数を実装すること。

  • 前回作成した「自然数を表す」ためのMyNatural型インスタンス
  • HaskellのInteger型インスタンス

自作したMyNatural型のおさらい

前回は、自然数を表すことを目的として、以下のシンプルな型をMyNaturalという型名で実装しました。
等号関係や順序関係もまだ実装していません(笑

現在のところ、自然数における

  • 0の存在
  • 「次の値」の存在

のみを表現しています。

data MyNatural = Zero | Successor MyNatural deriving Show

このMyNatural型ではデータコンストラクタZeroとSuccessorを用いて、

  • 0はZero
  • 1はSuccessor Zero
  • 2はSuccessor (Successor Zero)
  • 3は $\cdots$

というように自然数を表そうとしています。

ですが、例えば100を表そうとすると、Successorを100回書かなければいけないので大変です。
そこで、Integer型とMyNatural型を対応づける関数を作成してみようと思います。
(数字って偉大ですね。)

Integer型からMyNatural型への変換関数 

integerToMyNatural :: Integer -> MyNatural 
integerToMyNatural 0 = Zero
integerToMyNatural x = Successor (integerToMyNatural (pred x))

predは引数に-1して返すHaskellで用意されている関数です。(succの反対)
xに負の値を許容してしまうと、自然数型を自作する意味がなくなってしまいます。
というか、負の値を与えるとこの関数は発散する。。。

バリデーションは今後検討・実装していくことにして、
一旦、0以上の値を受け取ると仮定して進めます。

MyNatural型からInteger型への変換関数 

myNaturalToInteger :: MyNatural -> Integer 
myNaturalToInteger Zero = 0
myNaturalToInteger (Successor x) = succ (myNaturalToInteger x)

こちらは引数のMyNatural型がZeroに収束していくように、関数を再帰的に呼んでいるので、発散することはない、はず。

1+2=3 をMyNatural型で計算しInteger型に変換

さて、前回実装したMyNatural型での加算関数myAddと上記2つの変換関数を使用して、
$1+2=3$
を表現してみようと思います。

以下のmain関数では、まずInteger型の1と2をMyNatural型に変換してmyAdd(MyNatural型での加算)の計算をします。
そのあとprint関数で計算結果を

  • 変換したInteger型
  • そのままのMyNatural型

でそれぞれ出力します。

main :: IO ()
main = do
  print $ myNaturalToInteger 
    (myAdd (integerToMyNatural 1) (integerToMyNatural 2) )
  print $ myAdd (integerToMyNatural 1) (integerToMyNatural 2)

data MyNatural = Zero | Successor MyNatural deriving Show

myAdd :: MyNatural -> MyNatural -> MyNatural
myAdd Zero y = y
myAdd (Successor x) y = Successor (myAdd x y) 

myNaturalToInteger :: MyNatural -> Integer 
myNaturalToInteger Zero = 0
myNaturalToInteger (Successor x) = succ (myNaturalToInteger x)

integerToMyNatural ::Integer -> MyNatural 
integerToMyNatural 0 = Zero
integerToMyNatural x = Successor (integerToMyNatural (pred x))

実行すると、print関数で計算結果が

3
Successor (Successor (Successor Zero))

と出力されていて満足です(笑

今回は以上です。
最後までご覧いただきありがとうございました。
<(_ _)>

これまでの記事

Haskellを使いながら計算論 【1】自作自然数型を定義し、加算関数をHaskellで帰納的に定義する

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0