定義したメソッド
自作クラスを宣言するときに、定義するクラスが用いるデータ型に制約を与えるのと同時に、そのクラスのインスタンスが持ちうる値の範囲や、長さの範囲にまで、制約を与えることができる言語は、依存型や篩型の型クラスを宣言できる言語として、知られています。
Idrisやv6.11以降のRacket言語が、これらの型を宣言し、静的な型検査を行うことができる言語です。
・Dependent Types と Refinement Types の違い
・Refinement Types For Haskell
・型をさらに拡張するーーRefinement Typesについて
・LiquidHaskell のインストールと学習方法
・Liquid Haskell で普通の型システムの上を行け #NGK2017B
これらの言語は、関数型言語です。Haskellが、関数型言語として、Qiitaでも多くの良質な記事が書かれています。
元々は手続き型言語であったPythonでも、以下のように、関数型言語のスタイルを取り入れる動きが進行中です。
- __型アノテーション__の導入(typingモジュール)
- 外部のツールとして、静的な型検査を行うmypyの登場
- mapやreduceの多様
- 破壊的代入が可能なListではなく、破壊的代入が言語レベルの仕様で禁止されているtuple型の利用を推奨するプログラミングスタイルの普及
こうした流れを受けて、この記事では、__Pythonで「依存型」クラスを実現する__ための一歩として、ある配列オブジェクトの__要素が持つデータ型__と、__配列全体の長さ__を検査するメソッドを定義してみました。
定義したメソッドの返り値は、bool型(TrueもしくはFalseのいずれか)です。
定義するメソッドが行う型検査の内容
- 第1引数に渡した配列の要素がすべてstr型のオブジェクトであるかどうか。
- 配列の要素数が第2引数に渡した数値未満であるかどうか。
以下、Ipythonの対話型インタプリタで実行しました。
In [1]: from typing import List, Sequence, TypeVar
In [2]: T = TypeVar('T')
In [3]: def func_(x: List[T], n: int) -> bool:
...: condition_1 = (len(x) < n)
...: condition_2 = not(False in [isinstance(elem, str) for elem in x])
...: condition = (condition_1 and condition_2)
...: return condition
...:
( 動作確認 )
以下の2つの条件が揃った場合のみ、Trueが帰ることが確認できました。
( AND条件 )
- 第1引数に渡した配列の要素がすべてstr型のオブジェクトである。
- 配列の要素数が第2引数に渡した数値未満である。
In [4]: test_list = [1, 2, 3, "a", 1, 5, 9, 10, 17]
In [5]: result = func_(test_list, 7)
In [6]: print(result)
False
In [7]: test_lis2t = [1, 2, 3, "a", 1]
In [8]: test_list2 = [1, 2, 3, "a", 1]
In [9]: result = func_(test_list2, 7)
In [10]: print(result)
False
In [11]: test_list = [1, 2, 3, 1, 5, 9, 10, 17]
In [12]: result = func_(test_list, 7)
In [13]: print(result)
False
In [14]: test_list2 = [1, 2, 3]
In [15]: result = func_(test_list2, 7)
In [16]: print(result)
False
In [17]: test_list3 = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
In [18]: result3 = func_(test_list3, 7)
In [19]: print(result3)
False
In [20]: test_list4 = ["a", "b", "c"]
In [21]: result4 = func_(test_list4, 7)
In [22]: print(result4)
True
In [23]: test_list5 = ["a", "b", 1, 3]
In [24]: result5 = func_(test_list5, 7)
In [25]: print(result5)
False
In [26]: