Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Pythonで鉄道指向プログラミング
Search
USABARASHI
July 20, 2022
Programming
1.6k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Pythonで鉄道指向プログラミング
USABARASHI
July 20, 2022
More Decks by USABARASHI
See All by USABARASHI
Nix入門 devShell
usabarashi
2
750
Other Decks in Programming
See All in Programming
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
640
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
290
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
140
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
120
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
4
600
Kiroで創り、AgentCoreで繋ぐ!AWSで実践する「AI-DLC」から「AIエージェント統合」までの最新地図
licux
3
360
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
460
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
130
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
0
400
高専キャリア LT 発表内容
crysta1221
6
5.6k
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
3
500
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
270
Featured
See All Featured
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
260
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Accessibility Awareness
sabderemane
1
200
The SEO identity crisis: Don't let AI make you average
varn
0
550
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
510
Typedesign – Prime Four
hannesfritz
42
3.2k
Exploring anti-patterns in Rails
aemeredith
3
500
[SF Ruby Conf 2025] Rails X
palkan
2
1.4k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
690
Transcript
Pythonで 鉄道指向プログラミング Haskell, Scala, F#, Rust, … etc のアレ Python
3.10, Pylance v2022.6.30 2022/07/20 @usabarashi 1
どんな人?こんな人 Python歴 • 〜2019/09: Elm, Scala, TSを書いていた • 2019/10: Pythonを触り始める
• 2022/06: 未だに「Pythonicって何やねん...」という日々 2
鉄道指向 プログラミング 3
失敗/成功の判断を掛け合わせる • Railway Oriented Programing • Domain Modeling Made Functional
- Chaining Result-Generating Functional • レールに乗らない失敗 /成功はType Errorになる • 失敗したら成功のレールには戻らな い • いつ失敗しても失敗のレールに乗る • 最後まで成功すると成功になる • 失敗の種類が決まっている 4
Haskell: do notation 5
Scala: For Comprehension 6
F#: Computation Expression 7
Rust: Question mark operator 8
Pythonで再現してみる 9
Python仕様 • from typing import Callable, Generic, TypeAlias, TypeVar ◦
T = TypeVar(“T”) ◦ class List(Generic[T]): ▪ Tは型が束縛される変数なので型変数 ▪ List[T]はT型を処理するList型 ▪ List[int]はint型を処理するList型 ▪ Callable[[A, B], C]はA型, B型を引数にとりC型を返却する関数 • from collections.abc import Generator ◦ variable = yield process() ◦ StopIteration.value ▪ Generator[Y, S, R] <: Iterator <: Iterable ▪ Y: yieldの右側のprocessの結果の型変数 ▪ S: = yieldの左側のvariableに束縛する値の型変数 ▪ R: StopIteration.valueの型変数 10
失敗/成功の型を定義する 失敗/成功の定義 class Either(Generic[L, R]): Either[L, R] 失敗の定義 class Left(Either[L,
R): Left[L, R] 成功の定義 class Right(Either[L, R]): Right[L, R] 11
失敗/成功の型を定義する 失敗/成功のどちらかを返す def either(...) -> Either[L, R]: if …: return
Left[L, R](...) else: return Right[L, R](...) 12
シグネチャに失敗の値の型を定義する 失敗したらLeft[str, Any]を返す return Left[str, Any] 成功したらRight[str, Any]を返す return Right[str,
Any] ※ TypeAliasから型変数を指定できる EitherDo: TypeAlias = Generator[Either[L, Any], None, R] 13
EitherDo: TypeAlias = Generator[Either[L, Any], None, R] 上から下へ, 右から左への二次元と考える と理解しやすい
↓ =yield from Left[L, Any] ↓ Any=yield from Right[L, Any] return R StopIteration.value 一連の処理をGenerator関数で定義する 14
失敗を早期リターンする ↓ =yield from Left[L, Any] サブジェネレーターからLeft[L, Any]を貰う class Either(Generic[L,
R]): @abstractmethod def __iter__(self) -> Generator[Either[L, R], None, R]: 失敗ならLeft[L, Any]をそのままリターンする @staticmethod def do(...) -> Callable[P, Either[L, R]] … except ShortCircuit as short_circuit: return cast(Monad[A], short_circuit.state) …. ※ 失敗パターンはシグネチャに明記され ている 15
途中の処理結果を束縛する ↓ Any=yield from Right[L, Any] サブジェネレーターからRight[L, Any]を貰う class Either(Generic[L,
R]): @abstractmethod def __iter__(self) -> Generator[Either[L, R], None, R]: 成功ならサブジェネレーターのRをsendする @staticmethod def do(...) -> Callable[P, Either[L, R]] … case _ if type(yield_) is type(composite): composite = composite.flat_map(lambda _: cast(Monad[Any], yield_)) ※ サブジェネレーターの R: StopIteration.valueで暗黙的に束縛される 16
成功をリターンする return R StopIteration.value yieldがなくなったらreturnに相当する StopIteration.valueをリターンする @staticmethod def do(...) ->
Callable[P, Either[L, R]] … return cast(Monad[A], composite.map(lambda _: result)) ※ 成功のRight[L, R]型へあわせる 17
失敗/成功のどちらかだけ である可能性を定義する SubType: TypeAlias = Left[L, R] | Right[L, R]
@property def pattern(self) -> SubType[L, R]: return self ※ どこから継承されるか分からないので 可能性を具体的に制限する ※ 動的なメソッドだとtype narrowingが固 定されないのでpropertyで静的な値として 定義する pattern() pattern 18
失敗/成功を判定する class Left(Either[L, R]): __match_args__ = ("value",) self.value class Right(Either[L,
R]): __match_args__ = ("value",) self.value ※ パターンを網羅できていない場合は警 告が表示される 19
同じ構文で記述する: nullかも知れない • if var is None: • if var
is not None: • if isinstance(var, None): とか書かない ※ if Xxxx is type(var)は type narrowingされない 20
同じ構文で記述する: 例外が発生するかも知れない try: … except ExceptionA as exception_a: … raise
ExceptionB from exception_a except Exception: … raise else: … とか書かない ※ どこからどのようなExceptionがraiseされているか 静的解析できない 例外とは何か例外的なもの(ある意味、あきらめ)を表現するものであるとした場合、失敗は想定できる結 果であるため、その失敗を例外としてモデリングすることは意味的におかしいことになってしまいます。 セキュア・バイ・デザイン - 安全性を考えた処理失敗時の対策 21
文でなく式にする 文: 処理 式: 結果 = 処理 def method(self: A,
function: Callable[[A], B]) -> B: … result = sample_a .method(lambda self: SampleB(self.value)) def fold( self, left: Callable[[L], U], right: Callable[[R], U] ) -> U: … json_result = either.fold( left=lambda error: Json変換処理(error), right=lambda result: Json変換処理(result) ) 22
で, 実務で使えるの? 23
ビジネスロジック型パズル 24
ビジネスロジック型パズル 25
ビジネスロジック型パズル 26
ビジネスロジック型パズル 27
エンタープライズの鉄道 • 申請 ◦ 決裁 ◦ 未承認, 却下 • 機密
◦ 参照権限あり ◦ 参照権限なし 28
参考文献 • PyPI: pycategory • Railway Oriented Programing • Domain
Modeling Made Functional • 明日から使える実践エラーハンドリング • セキュア・バイ・デザイン • 圏論とモナドシリーズ • Scala, Scalaz, Cats 29