@k2works/claude-code-booster 6.1.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (622) hide show
  1. package/lib/assets/.claude/skills/practicing-getting-start-tdd/SKILL.md +3 -7
  2. package/lib/assets/docs/article/index.md +16 -41
  3. package/lib/assets/docs/assets/js/extra.js +5 -1
  4. package/lib/assets/docs/assets/js/mathjax.js +27 -0
  5. package/lib/assets/docs/index.md +1 -1
  6. package/lib/assets/mkdocs.yml +6 -7
  7. package/lib/assets/ops/docker/mkdoc/Dockerfile +19 -19
  8. package/lib/assets/package.json +1 -1
  9. package/package.json +1 -1
  10. package/lib/assets/docs/article/functional-desgin-ppp/all/01-immutability-and-data-transformation.md +0 -484
  11. package/lib/assets/docs/article/functional-desgin-ppp/all/02-function-composition.md +0 -528
  12. package/lib/assets/docs/article/functional-desgin-ppp/all/03-polymorphism.md +0 -546
  13. package/lib/assets/docs/article/functional-desgin-ppp/all/04-data-validation.md +0 -309
  14. package/lib/assets/docs/article/functional-desgin-ppp/all/05-property-based-testing.md +0 -329
  15. package/lib/assets/docs/article/functional-desgin-ppp/all/06-tdd-and-functional.md +0 -507
  16. package/lib/assets/docs/article/functional-desgin-ppp/all/07-composite-pattern.md +0 -307
  17. package/lib/assets/docs/article/functional-desgin-ppp/all/08-decorator-pattern.md +0 -300
  18. package/lib/assets/docs/article/functional-desgin-ppp/all/09-adapter-pattern.md +0 -345
  19. package/lib/assets/docs/article/functional-desgin-ppp/all/10-strategy-pattern.md +0 -312
  20. package/lib/assets/docs/article/functional-desgin-ppp/all/11-command-pattern.md +0 -295
  21. package/lib/assets/docs/article/functional-desgin-ppp/all/12-visitor-pattern.md +0 -331
  22. package/lib/assets/docs/article/functional-desgin-ppp/all/13-abstract-factory-pattern.md +0 -328
  23. package/lib/assets/docs/article/functional-desgin-ppp/all/14-abstract-server-pattern.md +0 -374
  24. package/lib/assets/docs/article/functional-desgin-ppp/all/15-gossiping-bus-drivers.md +0 -165
  25. package/lib/assets/docs/article/functional-desgin-ppp/all/16-payroll-system.md +0 -187
  26. package/lib/assets/docs/article/functional-desgin-ppp/all/17-video-rental-system.md +0 -321
  27. package/lib/assets/docs/article/functional-desgin-ppp/all/18-concurrency-system.md +0 -296
  28. package/lib/assets/docs/article/functional-desgin-ppp/all/19-wa-tor-simulation.md +0 -295
  29. package/lib/assets/docs/article/functional-desgin-ppp/all/20-pattern-interactions.md +0 -283
  30. package/lib/assets/docs/article/functional-desgin-ppp/all/21-best-practices.md +0 -303
  31. package/lib/assets/docs/article/functional-desgin-ppp/all/22-oo-to-fp-migration.md +0 -346
  32. package/lib/assets/docs/article/functional-desgin-ppp/all/index.md +0 -388
  33. package/lib/assets/docs/article/functional-desgin-ppp/clojure/01-immutability-and-data-transformation.md +0 -282
  34. package/lib/assets/docs/article/functional-desgin-ppp/clojure/02-function-composition.md +0 -389
  35. package/lib/assets/docs/article/functional-desgin-ppp/clojure/03-polymorphism.md +0 -393
  36. package/lib/assets/docs/article/functional-desgin-ppp/clojure/04-clojure-spec.md +0 -359
  37. package/lib/assets/docs/article/functional-desgin-ppp/clojure/05-property-based-testing.md +0 -361
  38. package/lib/assets/docs/article/functional-desgin-ppp/clojure/06-tdd-in-functional.md +0 -392
  39. package/lib/assets/docs/article/functional-desgin-ppp/clojure/07-composite-pattern.md +0 -538
  40. package/lib/assets/docs/article/functional-desgin-ppp/clojure/08-decorator-pattern.md +0 -404
  41. package/lib/assets/docs/article/functional-desgin-ppp/clojure/09-adapter-pattern.md +0 -408
  42. package/lib/assets/docs/article/functional-desgin-ppp/clojure/10-strategy-pattern.md +0 -494
  43. package/lib/assets/docs/article/functional-desgin-ppp/clojure/11-command-pattern.md +0 -575
  44. package/lib/assets/docs/article/functional-desgin-ppp/clojure/12-visitor-pattern.md +0 -576
  45. package/lib/assets/docs/article/functional-desgin-ppp/clojure/13-abstract-factory-pattern.md +0 -484
  46. package/lib/assets/docs/article/functional-desgin-ppp/clojure/14-abstract-server-pattern.md +0 -471
  47. package/lib/assets/docs/article/functional-desgin-ppp/clojure/15-gossiping-bus-drivers.md +0 -334
  48. package/lib/assets/docs/article/functional-desgin-ppp/clojure/16-payroll-system.md +0 -410
  49. package/lib/assets/docs/article/functional-desgin-ppp/clojure/17-video-rental-system.md +0 -459
  50. package/lib/assets/docs/article/functional-desgin-ppp/clojure/18-concurrency-system.md +0 -484
  51. package/lib/assets/docs/article/functional-desgin-ppp/clojure/19-wator-simulation.md +0 -748
  52. package/lib/assets/docs/article/functional-desgin-ppp/clojure/20-pattern-interactions.md +0 -576
  53. package/lib/assets/docs/article/functional-desgin-ppp/clojure/21-best-practices.md +0 -527
  54. package/lib/assets/docs/article/functional-desgin-ppp/clojure/22-oo-to-fp-migration.md +0 -541
  55. package/lib/assets/docs/article/functional-desgin-ppp/clojure/index.md +0 -241
  56. package/lib/assets/docs/article/functional-desgin-ppp/elixir/01-immutability-and-data-transformation.md +0 -392
  57. package/lib/assets/docs/article/functional-desgin-ppp/elixir/02-function-composition.md +0 -383
  58. package/lib/assets/docs/article/functional-desgin-ppp/elixir/03-polymorphism.md +0 -384
  59. package/lib/assets/docs/article/functional-desgin-ppp/elixir/04-data-validation.md +0 -204
  60. package/lib/assets/docs/article/functional-desgin-ppp/elixir/05-property-based-testing.md +0 -277
  61. package/lib/assets/docs/article/functional-desgin-ppp/elixir/06-tdd-and-fp.md +0 -303
  62. package/lib/assets/docs/article/functional-desgin-ppp/elixir/07-effects-and-pure-functions.md +0 -173
  63. package/lib/assets/docs/article/functional-desgin-ppp/elixir/08-error-handling-strategies.md +0 -177
  64. package/lib/assets/docs/article/functional-desgin-ppp/elixir/09-io-and-external-systems.md +0 -263
  65. package/lib/assets/docs/article/functional-desgin-ppp/elixir/10-concurrency-patterns.md +0 -278
  66. package/lib/assets/docs/article/functional-desgin-ppp/elixir/11-command-pattern.md +0 -157
  67. package/lib/assets/docs/article/functional-desgin-ppp/elixir/12-visitor-pattern.md +0 -185
  68. package/lib/assets/docs/article/functional-desgin-ppp/elixir/13-abstract-factory-pattern.md +0 -613
  69. package/lib/assets/docs/article/functional-desgin-ppp/elixir/14-abstract-server-pattern.md +0 -738
  70. package/lib/assets/docs/article/functional-desgin-ppp/elixir/15-gossiping-bus-drivers.md +0 -300
  71. package/lib/assets/docs/article/functional-desgin-ppp/elixir/16-payroll-system.md +0 -429
  72. package/lib/assets/docs/article/functional-desgin-ppp/elixir/17-video-rental-system.md +0 -328
  73. package/lib/assets/docs/article/functional-desgin-ppp/elixir/18-concurrency-system.md +0 -475
  74. package/lib/assets/docs/article/functional-desgin-ppp/elixir/19-wator-simulation.md +0 -532
  75. package/lib/assets/docs/article/functional-desgin-ppp/elixir/20-pattern-interactions.md +0 -296
  76. package/lib/assets/docs/article/functional-desgin-ppp/elixir/21-best-practices.md +0 -349
  77. package/lib/assets/docs/article/functional-desgin-ppp/elixir/22-oo-to-fp-migration.md +0 -404
  78. package/lib/assets/docs/article/functional-desgin-ppp/elixir/index.md +0 -248
  79. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/01-immutability-and-data-transformation.md +0 -393
  80. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/02-function-composition.md +0 -461
  81. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/03-polymorphism.md +0 -504
  82. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/04-data-validation.md +0 -425
  83. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/05-property-based-testing.md +0 -391
  84. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/06-tdd-functional.md +0 -696
  85. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/07-composite-pattern.md +0 -451
  86. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/08-decorator-pattern.md +0 -488
  87. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/09-adapter-pattern.md +0 -488
  88. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/10-strategy-pattern.md +0 -436
  89. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/11-command-pattern.md +0 -437
  90. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/12-visitor-pattern.md +0 -348
  91. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/13-abstract-factory-pattern.md +0 -318
  92. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/14-abstract-server-pattern.md +0 -605
  93. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/15-gossiping-bus-drivers.md +0 -364
  94. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/16-payroll-system.md +0 -359
  95. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/17-video-rental-system.md +0 -423
  96. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/18-concurrency-system.md +0 -376
  97. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/19-wator-simulation.md +0 -412
  98. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/20-pattern-interactions.md +0 -300
  99. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/21-best-practices.md +0 -333
  100. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/22-oo-to-fp-migration.md +0 -341
  101. package/lib/assets/docs/article/functional-desgin-ppp/fsharp/index.md +0 -274
  102. package/lib/assets/docs/article/functional-desgin-ppp/haskell/01-immutability-and-data-transformation.md +0 -307
  103. package/lib/assets/docs/article/functional-desgin-ppp/haskell/02-function-composition.md +0 -313
  104. package/lib/assets/docs/article/functional-desgin-ppp/haskell/03-polymorphism.md +0 -371
  105. package/lib/assets/docs/article/functional-desgin-ppp/haskell/04-data-validation.md +0 -266
  106. package/lib/assets/docs/article/functional-desgin-ppp/haskell/05-property-based-testing.md +0 -263
  107. package/lib/assets/docs/article/functional-desgin-ppp/haskell/06-tdd-functional.md +0 -292
  108. package/lib/assets/docs/article/functional-desgin-ppp/haskell/07-composite-pattern.md +0 -404
  109. package/lib/assets/docs/article/functional-desgin-ppp/haskell/08-decorator-pattern.md +0 -328
  110. package/lib/assets/docs/article/functional-desgin-ppp/haskell/09-adapter-pattern.md +0 -391
  111. package/lib/assets/docs/article/functional-desgin-ppp/haskell/10-strategy-pattern.md +0 -296
  112. package/lib/assets/docs/article/functional-desgin-ppp/haskell/11-command-pattern.md +0 -312
  113. package/lib/assets/docs/article/functional-desgin-ppp/haskell/12-visitor-pattern.md +0 -335
  114. package/lib/assets/docs/article/functional-desgin-ppp/haskell/13-abstract-factory-pattern.md +0 -341
  115. package/lib/assets/docs/article/functional-desgin-ppp/haskell/14-abstract-server-pattern.md +0 -388
  116. package/lib/assets/docs/article/functional-desgin-ppp/haskell/15-gossiping-bus-drivers.md +0 -186
  117. package/lib/assets/docs/article/functional-desgin-ppp/haskell/16-payroll-system.md +0 -228
  118. package/lib/assets/docs/article/functional-desgin-ppp/haskell/17-video-rental-system.md +0 -253
  119. package/lib/assets/docs/article/functional-desgin-ppp/haskell/18-concurrency-system.md +0 -372
  120. package/lib/assets/docs/article/functional-desgin-ppp/haskell/19-wator-simulation.md +0 -447
  121. package/lib/assets/docs/article/functional-desgin-ppp/haskell/20-pattern-interactions.md +0 -334
  122. package/lib/assets/docs/article/functional-desgin-ppp/haskell/21-best-practices.md +0 -412
  123. package/lib/assets/docs/article/functional-desgin-ppp/haskell/22-oo-to-fp-migration.md +0 -478
  124. package/lib/assets/docs/article/functional-desgin-ppp/haskell/index.md +0 -174
  125. package/lib/assets/docs/article/functional-desgin-ppp/index.md +0 -90
  126. package/lib/assets/docs/article/functional-desgin-ppp/rust/01-immutability-and-data-transformation.md +0 -459
  127. package/lib/assets/docs/article/functional-desgin-ppp/rust/02-function-composition.md +0 -472
  128. package/lib/assets/docs/article/functional-desgin-ppp/rust/03-polymorphism.md +0 -434
  129. package/lib/assets/docs/article/functional-desgin-ppp/rust/04-data-validation.md +0 -282
  130. package/lib/assets/docs/article/functional-desgin-ppp/rust/05-property-based-testing.md +0 -256
  131. package/lib/assets/docs/article/functional-desgin-ppp/rust/06-tdd-and-functional.md +0 -850
  132. package/lib/assets/docs/article/functional-desgin-ppp/rust/07-composite-pattern.md +0 -393
  133. package/lib/assets/docs/article/functional-desgin-ppp/rust/08-decorator-pattern.md +0 -392
  134. package/lib/assets/docs/article/functional-desgin-ppp/rust/09-adapter-pattern.md +0 -348
  135. package/lib/assets/docs/article/functional-desgin-ppp/rust/10-strategy-pattern.md +0 -340
  136. package/lib/assets/docs/article/functional-desgin-ppp/rust/11-command-pattern.md +0 -365
  137. package/lib/assets/docs/article/functional-desgin-ppp/rust/12-visitor-pattern.md +0 -388
  138. package/lib/assets/docs/article/functional-desgin-ppp/rust/13-abstract-factory-pattern.md +0 -370
  139. package/lib/assets/docs/article/functional-desgin-ppp/rust/14-abstract-server-pattern.md +0 -401
  140. package/lib/assets/docs/article/functional-desgin-ppp/rust/15-gossiping-bus-drivers.md +0 -309
  141. package/lib/assets/docs/article/functional-desgin-ppp/rust/16-payroll-system.md +0 -306
  142. package/lib/assets/docs/article/functional-desgin-ppp/rust/17-video-rental-system.md +0 -313
  143. package/lib/assets/docs/article/functional-desgin-ppp/rust/18-concurrency-system.md +0 -324
  144. package/lib/assets/docs/article/functional-desgin-ppp/rust/19-wator-simulation.md +0 -320
  145. package/lib/assets/docs/article/functional-desgin-ppp/rust/20-pattern-interactions.md +0 -313
  146. package/lib/assets/docs/article/functional-desgin-ppp/rust/21-best-practices.md +0 -345
  147. package/lib/assets/docs/article/functional-desgin-ppp/rust/22-oo-to-fp-migration.md +0 -358
  148. package/lib/assets/docs/article/functional-desgin-ppp/rust/index.md +0 -243
  149. package/lib/assets/docs/article/functional-desgin-ppp/scala/01-immutability-and-data-transformation.md +0 -337
  150. package/lib/assets/docs/article/functional-desgin-ppp/scala/02-function-composition.md +0 -357
  151. package/lib/assets/docs/article/functional-desgin-ppp/scala/03-polymorphism.md +0 -366
  152. package/lib/assets/docs/article/functional-desgin-ppp/scala/04-data-validation.md +0 -373
  153. package/lib/assets/docs/article/functional-desgin-ppp/scala/05-property-based-testing.md +0 -524
  154. package/lib/assets/docs/article/functional-desgin-ppp/scala/06-tdd-functional.md +0 -566
  155. package/lib/assets/docs/article/functional-desgin-ppp/scala/07-composite-pattern.md +0 -372
  156. package/lib/assets/docs/article/functional-desgin-ppp/scala/08-decorator-pattern.md +0 -336
  157. package/lib/assets/docs/article/functional-desgin-ppp/scala/09-adapter-pattern.md +0 -526
  158. package/lib/assets/docs/article/functional-desgin-ppp/scala/10-strategy-pattern.md +0 -450
  159. package/lib/assets/docs/article/functional-desgin-ppp/scala/11-command-pattern.md +0 -416
  160. package/lib/assets/docs/article/functional-desgin-ppp/scala/12-visitor-pattern.md +0 -388
  161. package/lib/assets/docs/article/functional-desgin-ppp/scala/13-abstract-factory-pattern.md +0 -407
  162. package/lib/assets/docs/article/functional-desgin-ppp/scala/14-abstract-server-pattern.md +0 -485
  163. package/lib/assets/docs/article/functional-desgin-ppp/scala/15-gossiping-bus-drivers.md +0 -400
  164. package/lib/assets/docs/article/functional-desgin-ppp/scala/16-payroll-system.md +0 -351
  165. package/lib/assets/docs/article/functional-desgin-ppp/scala/17-video-rental-system.md +0 -333
  166. package/lib/assets/docs/article/functional-desgin-ppp/scala/18-concurrency-system.md +0 -739
  167. package/lib/assets/docs/article/functional-desgin-ppp/scala/19-wator-simulation.md +0 -633
  168. package/lib/assets/docs/article/functional-desgin-ppp/scala/20-pattern-interactions.md +0 -521
  169. package/lib/assets/docs/article/functional-desgin-ppp/scala/21-best-practices.md +0 -442
  170. package/lib/assets/docs/article/functional-desgin-ppp/scala/22-oo-to-fp-migration.md +0 -697
  171. package/lib/assets/docs/article/functional-desgin-ppp/scala/index.md +0 -243
  172. package/lib/assets/docs/article/getting-start-docker-kubernetes/01-container-and-docker-basics.md +0 -341
  173. package/lib/assets/docs/article/getting-start-docker-kubernetes/02-container-deployment.md +0 -785
  174. package/lib/assets/docs/article/getting-start-docker-kubernetes/03-practical-container-build-deploy.md +0 -466
  175. package/lib/assets/docs/article/getting-start-docker-kubernetes/04-multi-container-application.md +0 -878
  176. package/lib/assets/docs/article/getting-start-docker-kubernetes/05-kubernetes-introduction.md +0 -585
  177. package/lib/assets/docs/article/getting-start-docker-kubernetes/06-kubernetes-deploy-cluster.md +0 -620
  178. package/lib/assets/docs/article/getting-start-docker-kubernetes/07-kubernetes-advanced.md +0 -621
  179. package/lib/assets/docs/article/getting-start-docker-kubernetes/08-kubernetes-packaging.md +0 -518
  180. package/lib/assets/docs/article/getting-start-docker-kubernetes/09-container-operations.md +0 -546
  181. package/lib/assets/docs/article/getting-start-docker-kubernetes/10-optimal-container-image.md +0 -640
  182. package/lib/assets/docs/article/getting-start-docker-kubernetes/11-continuous-delivery.md +0 -607
  183. package/lib/assets/docs/article/getting-start-docker-kubernetes/12-container-use-cases.md +0 -463
  184. package/lib/assets/docs/article/getting-start-docker-kubernetes/13-case-monolith-compose-vs-kustomize.md +0 -346
  185. package/lib/assets/docs/article/getting-start-docker-kubernetes/14-case-event-driven-kustomize-vs-helm.md +0 -324
  186. package/lib/assets/docs/article/getting-start-docker-kubernetes/15-case-escqrs-axon-kustomize-vs-helm.md +0 -297
  187. package/lib/assets/docs/article/getting-start-docker-kubernetes/16-case-escqrs-kafka-kustomize-vs-helm.md +0 -256
  188. package/lib/assets/docs/article/getting-start-docker-kubernetes/17-case-comparison-summary.md +0 -141
  189. package/lib/assets/docs/article/getting-start-docker-kubernetes/18-case-load-testing.md +0 -303
  190. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-a-dev-tools-setup.md +0 -274
  191. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-b-orchestration-environments.md +0 -530
  192. package/lib/assets/docs/article/getting-start-docker-kubernetes/appendix-c-tips.md +0 -519
  193. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-01-comic.png +0 -0
  194. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-02-comic.png +0 -0
  195. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-03-comic.png +0 -0
  196. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-04-comic.png +0 -0
  197. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-05-comic.png +0 -0
  198. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-06-comic.png +0 -0
  199. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-07-comic.png +0 -0
  200. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-08-comic.png +0 -0
  201. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-09-comic.png +0 -0
  202. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-10-comic.png +0 -0
  203. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-11-comic.png +0 -0
  204. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/chapter-12-comic.png +0 -0
  205. package/lib/assets/docs/article/getting-start-docker-kubernetes/images/overview-comic.png +0 -0
  206. package/lib/assets/docs/article/getting-start-docker-kubernetes/index.md +0 -82
  207. package/lib/assets/docs/article/getting-start-docker-kubernetes/outline.md +0 -220
  208. package/lib/assets/docs/article/getting-start-tdd/clojure/01-todo-list-and-first-test.md +0 -175
  209. package/lib/assets/docs/article/getting-start-tdd/clojure/02-fake-it-and-triangulation.md +0 -171
  210. package/lib/assets/docs/article/getting-start-tdd/clojure/03-obvious-implementation-and-refactoring.md +0 -144
  211. package/lib/assets/docs/article/getting-start-tdd/clojure/04-version-control-and-conventional-commits.md +0 -97
  212. package/lib/assets/docs/article/getting-start-tdd/clojure/05-package-management-and-static-analysis.md +0 -308
  213. package/lib/assets/docs/article/getting-start-tdd/clojure/06-task-runner-and-ci-cd.md +0 -250
  214. package/lib/assets/docs/article/getting-start-tdd/clojure/07-protocols-and-records.md +0 -140
  215. package/lib/assets/docs/article/getting-start-tdd/clojure/08-multimethods-and-design-patterns.md +0 -139
  216. package/lib/assets/docs/article/getting-start-tdd/clojure/09-namespaces-and-module-design.md +0 -136
  217. package/lib/assets/docs/article/getting-start-tdd/clojure/10-higher-order-functions-and-composition.md +0 -123
  218. package/lib/assets/docs/article/getting-start-tdd/clojure/11-persistent-data-and-pipeline.md +0 -147
  219. package/lib/assets/docs/article/getting-start-tdd/clojure/12-error-handling-and-spec.md +0 -170
  220. package/lib/assets/docs/article/getting-start-tdd/clojure/index.md +0 -65
  221. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter01.md +0 -241
  222. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter02.md +0 -253
  223. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter03.md +0 -211
  224. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter04.md +0 -101
  225. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter05.md +0 -265
  226. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter06.md +0 -204
  227. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter07.md +0 -223
  228. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter08.md +0 -258
  229. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter09.md +0 -183
  230. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter10.md +0 -175
  231. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter11.md +0 -201
  232. package/lib/assets/docs/article/getting-start-tdd/csharp/chapter12.md +0 -220
  233. package/lib/assets/docs/article/getting-start-tdd/csharp/index.md +0 -83
  234. package/lib/assets/docs/article/getting-start-tdd/elixir/01-todo-list-and-first-test.md +0 -96
  235. package/lib/assets/docs/article/getting-start-tdd/elixir/02-fake-it-and-triangulation.md +0 -104
  236. package/lib/assets/docs/article/getting-start-tdd/elixir/03-obvious-implementation-and-refactoring.md +0 -118
  237. package/lib/assets/docs/article/getting-start-tdd/elixir/04-version-control-and-conventional-commits.md +0 -105
  238. package/lib/assets/docs/article/getting-start-tdd/elixir/05-package-management-and-static-analysis.md +0 -97
  239. package/lib/assets/docs/article/getting-start-tdd/elixir/06-task-runner-and-ci-cd.md +0 -80
  240. package/lib/assets/docs/article/getting-start-tdd/elixir/07-structs-and-protocols.md +0 -119
  241. package/lib/assets/docs/article/getting-start-tdd/elixir/08-pattern-matching-and-guards.md +0 -117
  242. package/lib/assets/docs/article/getting-start-tdd/elixir/09-module-design-and-behaviours.md +0 -113
  243. package/lib/assets/docs/article/getting-start-tdd/elixir/10-higher-order-functions-and-pipeline.md +0 -187
  244. package/lib/assets/docs/article/getting-start-tdd/elixir/11-stream-and-lazy-evaluation.md +0 -151
  245. package/lib/assets/docs/article/getting-start-tdd/elixir/12-error-handling-and-with.md +0 -154
  246. package/lib/assets/docs/article/getting-start-tdd/elixir/index.md +0 -35
  247. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter01.md +0 -211
  248. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter02.md +0 -255
  249. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter03.md +0 -227
  250. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter04.md +0 -188
  251. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter05.md +0 -276
  252. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter06.md +0 -199
  253. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter07.md +0 -170
  254. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter08.md +0 -184
  255. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter09.md +0 -231
  256. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter10.md +0 -198
  257. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter11.md +0 -221
  258. package/lib/assets/docs/article/getting-start-tdd/fsharp/chapter12.md +0 -224
  259. package/lib/assets/docs/article/getting-start-tdd/fsharp/index.md +0 -71
  260. package/lib/assets/docs/article/getting-start-tdd/go/01-todo-list-and-first-test.md +0 -222
  261. package/lib/assets/docs/article/getting-start-tdd/go/02-fake-it-and-triangulation.md +0 -311
  262. package/lib/assets/docs/article/getting-start-tdd/go/03-obvious-implementation-and-refactoring.md +0 -348
  263. package/lib/assets/docs/article/getting-start-tdd/go/04-version-control-and-conventional-commits.md +0 -121
  264. package/lib/assets/docs/article/getting-start-tdd/go/05-package-management-and-static-analysis.md +0 -281
  265. package/lib/assets/docs/article/getting-start-tdd/go/06-task-runner-and-ci-cd.md +0 -242
  266. package/lib/assets/docs/article/getting-start-tdd/go/07-encapsulation-and-polymorphism.md +0 -402
  267. package/lib/assets/docs/article/getting-start-tdd/go/08-design-patterns.md +0 -430
  268. package/lib/assets/docs/article/getting-start-tdd/go/09-solid-principles-and-module-design.md +0 -408
  269. package/lib/assets/docs/article/getting-start-tdd/go/10-higher-order-functions-and-composition.md +0 -234
  270. package/lib/assets/docs/article/getting-start-tdd/go/11-immutable-data-and-pipeline.md +0 -304
  271. package/lib/assets/docs/article/getting-start-tdd/go/12-error-handling-and-type-safety.md +0 -419
  272. package/lib/assets/docs/article/getting-start-tdd/go/index.md +0 -83
  273. package/lib/assets/docs/article/getting-start-tdd/haskell/01-todo-list-and-first-test.md +0 -288
  274. package/lib/assets/docs/article/getting-start-tdd/haskell/02-fake-it-and-triangulation.md +0 -346
  275. package/lib/assets/docs/article/getting-start-tdd/haskell/03-obvious-implementation-and-refactoring.md +0 -266
  276. package/lib/assets/docs/article/getting-start-tdd/haskell/04-version-control-and-conventional-commits.md +0 -191
  277. package/lib/assets/docs/article/getting-start-tdd/haskell/05-package-management-and-static-analysis.md +0 -322
  278. package/lib/assets/docs/article/getting-start-tdd/haskell/06-task-runner-and-ci-cd.md +0 -318
  279. package/lib/assets/docs/article/getting-start-tdd/haskell/07-algebraic-data-types-and-type-classes.md +0 -421
  280. package/lib/assets/docs/article/getting-start-tdd/haskell/08-pattern-matching-and-guards.md +0 -399
  281. package/lib/assets/docs/article/getting-start-tdd/haskell/09-module-design-and-smart-constructors.md +0 -470
  282. package/lib/assets/docs/article/getting-start-tdd/haskell/10-higher-order-functions-and-currying.md +0 -443
  283. package/lib/assets/docs/article/getting-start-tdd/haskell/11-function-composition-and-point-free.md +0 -401
  284. package/lib/assets/docs/article/getting-start-tdd/haskell/12-monad-and-error-handling.md +0 -640
  285. package/lib/assets/docs/article/getting-start-tdd/haskell/index.md +0 -49
  286. package/lib/assets/docs/article/getting-start-tdd/index.md +0 -93
  287. package/lib/assets/docs/article/getting-start-tdd/integration/01-language-overview.md +0 -384
  288. package/lib/assets/docs/article/getting-start-tdd/integration/02-test-framework-comparison.md +0 -358
  289. package/lib/assets/docs/article/getting-start-tdd/integration/03-tdd-pattern-comparison.md +0 -454
  290. package/lib/assets/docs/article/getting-start-tdd/integration/04-type-system-comparison.md +0 -418
  291. package/lib/assets/docs/article/getting-start-tdd/integration/05-dev-environment-comparison.md +0 -339
  292. package/lib/assets/docs/article/getting-start-tdd/integration/06-learning-roadmap.md +0 -299
  293. package/lib/assets/docs/article/getting-start-tdd/integration/index.md +0 -69
  294. package/lib/assets/docs/article/getting-start-tdd/java/01-todo-list-and-first-test.md +0 -243
  295. package/lib/assets/docs/article/getting-start-tdd/java/02-fake-it-and-triangulation.md +0 -270
  296. package/lib/assets/docs/article/getting-start-tdd/java/03-obvious-implementation-and-refactoring.md +0 -194
  297. package/lib/assets/docs/article/getting-start-tdd/java/04-version-control-and-conventional-commits.md +0 -124
  298. package/lib/assets/docs/article/getting-start-tdd/java/05-package-management-and-static-analysis.md +0 -391
  299. package/lib/assets/docs/article/getting-start-tdd/java/06-task-runner-and-ci-cd.md +0 -281
  300. package/lib/assets/docs/article/getting-start-tdd/java/07-encapsulation-and-polymorphism.md +0 -635
  301. package/lib/assets/docs/article/getting-start-tdd/java/08-design-patterns.md +0 -402
  302. package/lib/assets/docs/article/getting-start-tdd/java/09-solid-principles-and-module-design.md +0 -319
  303. package/lib/assets/docs/article/getting-start-tdd/java/10-higher-order-functions-and-composition.md +0 -197
  304. package/lib/assets/docs/article/getting-start-tdd/java/11-immutable-data-and-pipeline.md +0 -176
  305. package/lib/assets/docs/article/getting-start-tdd/java/12-error-handling-and-type-safety.md +0 -214
  306. package/lib/assets/docs/article/getting-start-tdd/java/index.md +0 -61
  307. package/lib/assets/docs/article/getting-start-tdd/node/01-todo-list-and-first-test.md +0 -253
  308. package/lib/assets/docs/article/getting-start-tdd/node/02-fake-it-and-triangulation.md +0 -271
  309. package/lib/assets/docs/article/getting-start-tdd/node/03-obvious-implementation-and-refactoring.md +0 -178
  310. package/lib/assets/docs/article/getting-start-tdd/node/04-version-control-and-conventional-commits.md +0 -121
  311. package/lib/assets/docs/article/getting-start-tdd/node/05-package-management-and-static-analysis.md +0 -323
  312. package/lib/assets/docs/article/getting-start-tdd/node/06-task-runner-and-ci-cd.md +0 -244
  313. package/lib/assets/docs/article/getting-start-tdd/node/07-encapsulation-and-polymorphism.md +0 -336
  314. package/lib/assets/docs/article/getting-start-tdd/node/08-design-patterns.md +0 -331
  315. package/lib/assets/docs/article/getting-start-tdd/node/09-solid-principles-and-module-design.md +0 -294
  316. package/lib/assets/docs/article/getting-start-tdd/node/10-higher-order-functions-and-composition.md +0 -208
  317. package/lib/assets/docs/article/getting-start-tdd/node/11-immutable-data-and-pipeline.md +0 -216
  318. package/lib/assets/docs/article/getting-start-tdd/node/12-error-handling-and-type-safety.md +0 -304
  319. package/lib/assets/docs/article/getting-start-tdd/node/index.md +0 -56
  320. package/lib/assets/docs/article/getting-start-tdd/php/01-todo-list-and-first-test.md +0 -268
  321. package/lib/assets/docs/article/getting-start-tdd/php/02-fake-it-and-triangulation.md +0 -209
  322. package/lib/assets/docs/article/getting-start-tdd/php/03-obvious-implementation-and-refactoring.md +0 -257
  323. package/lib/assets/docs/article/getting-start-tdd/php/04-version-control-and-conventional-commits.md +0 -150
  324. package/lib/assets/docs/article/getting-start-tdd/php/05-package-management-and-static-analysis.md +0 -419
  325. package/lib/assets/docs/article/getting-start-tdd/php/06-task-runner-and-ci-cd.md +0 -330
  326. package/lib/assets/docs/article/getting-start-tdd/php/07-encapsulation-and-polymorphism.md +0 -380
  327. package/lib/assets/docs/article/getting-start-tdd/php/08-design-patterns.md +0 -461
  328. package/lib/assets/docs/article/getting-start-tdd/php/09-solid-principles-and-module-design.md +0 -468
  329. package/lib/assets/docs/article/getting-start-tdd/php/10-higher-order-functions-and-composition.md +0 -190
  330. package/lib/assets/docs/article/getting-start-tdd/php/11-immutable-data-and-pipeline.md +0 -274
  331. package/lib/assets/docs/article/getting-start-tdd/php/12-error-handling-and-type-safety.md +0 -316
  332. package/lib/assets/docs/article/getting-start-tdd/php/index.md +0 -84
  333. package/lib/assets/docs/article/getting-start-tdd/python/01-todo-list-and-first-test.md +0 -210
  334. package/lib/assets/docs/article/getting-start-tdd/python/02-fake-it-and-triangulation.md +0 -256
  335. package/lib/assets/docs/article/getting-start-tdd/python/03-obvious-implementation-and-refactoring.md +0 -208
  336. package/lib/assets/docs/article/getting-start-tdd/python/04-version-control-and-conventional-commits.md +0 -96
  337. package/lib/assets/docs/article/getting-start-tdd/python/05-package-management-and-static-analysis.md +0 -283
  338. package/lib/assets/docs/article/getting-start-tdd/python/06-task-runner-and-ci-cd.md +0 -199
  339. package/lib/assets/docs/article/getting-start-tdd/python/07-encapsulation-and-polymorphism.md +0 -217
  340. package/lib/assets/docs/article/getting-start-tdd/python/08-design-patterns.md +0 -181
  341. package/lib/assets/docs/article/getting-start-tdd/python/09-solid-principles-and-module-design.md +0 -139
  342. package/lib/assets/docs/article/getting-start-tdd/python/10-higher-order-functions-and-composition.md +0 -131
  343. package/lib/assets/docs/article/getting-start-tdd/python/11-immutable-data-and-pipeline.md +0 -125
  344. package/lib/assets/docs/article/getting-start-tdd/python/12-error-handling-and-type-safety.md +0 -135
  345. package/lib/assets/docs/article/getting-start-tdd/python/index.md +0 -55
  346. package/lib/assets/docs/article/getting-start-tdd/ruby/01-todo-list-and-first-test.md +0 -240
  347. package/lib/assets/docs/article/getting-start-tdd/ruby/02-fake-it-and-triangulation.md +0 -247
  348. package/lib/assets/docs/article/getting-start-tdd/ruby/03-obvious-implementation-and-refactoring.md +0 -237
  349. package/lib/assets/docs/article/getting-start-tdd/ruby/04-version-control-and-conventional-commits.md +0 -121
  350. package/lib/assets/docs/article/getting-start-tdd/ruby/05-package-management-and-static-analysis.md +0 -296
  351. package/lib/assets/docs/article/getting-start-tdd/ruby/06-task-runner-and-ci-cd.md +0 -257
  352. package/lib/assets/docs/article/getting-start-tdd/ruby/07-encapsulation-and-polymorphism.md +0 -288
  353. package/lib/assets/docs/article/getting-start-tdd/ruby/08-design-patterns.md +0 -338
  354. package/lib/assets/docs/article/getting-start-tdd/ruby/09-solid-principles-and-module-design.md +0 -205
  355. package/lib/assets/docs/article/getting-start-tdd/ruby/10-higher-order-functions-and-composition.md +0 -184
  356. package/lib/assets/docs/article/getting-start-tdd/ruby/11-immutable-data-and-pipeline.md +0 -246
  357. package/lib/assets/docs/article/getting-start-tdd/ruby/12-error-handling-and-type-safety.md +0 -407
  358. package/lib/assets/docs/article/getting-start-tdd/ruby/index.md +0 -83
  359. package/lib/assets/docs/article/getting-start-tdd/rust/01-todo-list-and-first-test.md +0 -220
  360. package/lib/assets/docs/article/getting-start-tdd/rust/02-fake-it-and-triangulation.md +0 -273
  361. package/lib/assets/docs/article/getting-start-tdd/rust/03-obvious-implementation-and-refactoring.md +0 -242
  362. package/lib/assets/docs/article/getting-start-tdd/rust/04-version-control-and-conventional-commits.md +0 -101
  363. package/lib/assets/docs/article/getting-start-tdd/rust/05-package-management-and-static-analysis.md +0 -221
  364. package/lib/assets/docs/article/getting-start-tdd/rust/06-task-runner-and-ci-cd.md +0 -173
  365. package/lib/assets/docs/article/getting-start-tdd/rust/07-encapsulation-and-polymorphism.md +0 -151
  366. package/lib/assets/docs/article/getting-start-tdd/rust/08-design-patterns.md +0 -154
  367. package/lib/assets/docs/article/getting-start-tdd/rust/09-solid-principles-and-module-design.md +0 -119
  368. package/lib/assets/docs/article/getting-start-tdd/rust/10-higher-order-functions-and-composition.md +0 -103
  369. package/lib/assets/docs/article/getting-start-tdd/rust/11-immutable-data-and-pipeline.md +0 -114
  370. package/lib/assets/docs/article/getting-start-tdd/rust/12-error-handling-and-type-safety.md +0 -121
  371. package/lib/assets/docs/article/getting-start-tdd/rust/index.md +0 -83
  372. package/lib/assets/docs/article/getting-start-tdd/scala/01-todo-list-and-first-test.md +0 -120
  373. package/lib/assets/docs/article/getting-start-tdd/scala/02-fake-it-and-triangulation.md +0 -116
  374. package/lib/assets/docs/article/getting-start-tdd/scala/03-obvious-implementation-and-refactoring.md +0 -108
  375. package/lib/assets/docs/article/getting-start-tdd/scala/04-version-control-and-conventional-commits.md +0 -132
  376. package/lib/assets/docs/article/getting-start-tdd/scala/05-package-management-and-static-analysis.md +0 -205
  377. package/lib/assets/docs/article/getting-start-tdd/scala/06-task-runner-and-ci-cd.md +0 -195
  378. package/lib/assets/docs/article/getting-start-tdd/scala/07-case-classes-and-traits.md +0 -148
  379. package/lib/assets/docs/article/getting-start-tdd/scala/08-pattern-matching-and-sealed-traits.md +0 -115
  380. package/lib/assets/docs/article/getting-start-tdd/scala/09-packages-and-module-design.md +0 -84
  381. package/lib/assets/docs/article/getting-start-tdd/scala/10-higher-order-functions-and-composition.md +0 -113
  382. package/lib/assets/docs/article/getting-start-tdd/scala/11-collections-and-lazy-evaluation.md +0 -103
  383. package/lib/assets/docs/article/getting-start-tdd/scala/12-error-handling-and-type-safety.md +0 -101
  384. package/lib/assets/docs/article/getting-start-tdd/scala/index.md +0 -65
  385. package/lib/assets/docs/article/grokking-concurrency/all/index.md +0 -403
  386. package/lib/assets/docs/article/grokking-concurrency/all/part-1-ch02-sequential.md +0 -563
  387. package/lib/assets/docs/article/grokking-concurrency/all/part-2-ch04-05-threads.md +0 -478
  388. package/lib/assets/docs/article/grokking-concurrency/all/part-3-ch06-multitasking.md +0 -529
  389. package/lib/assets/docs/article/grokking-concurrency/all/part-4-ch07-parallel-patterns.md +0 -429
  390. package/lib/assets/docs/article/grokking-concurrency/all/part-5-ch08-09-synchronization.md +0 -519
  391. package/lib/assets/docs/article/grokking-concurrency/all/part-6-ch10-11-nonblocking-io.md +0 -444
  392. package/lib/assets/docs/article/grokking-concurrency/all/part-7-ch12-async.md +0 -474
  393. package/lib/assets/docs/article/grokking-concurrency/all/part-8-ch13-mapreduce.md +0 -386
  394. package/lib/assets/docs/article/grokking-concurrency/clojure/index.md +0 -106
  395. package/lib/assets/docs/article/grokking-concurrency/clojure/part-1.md +0 -107
  396. package/lib/assets/docs/article/grokking-concurrency/clojure/part-2.md +0 -100
  397. package/lib/assets/docs/article/grokking-concurrency/clojure/part-3.md +0 -121
  398. package/lib/assets/docs/article/grokking-concurrency/clojure/part-4.md +0 -122
  399. package/lib/assets/docs/article/grokking-concurrency/clojure/part-5.md +0 -117
  400. package/lib/assets/docs/article/grokking-concurrency/clojure/part-6.md +0 -88
  401. package/lib/assets/docs/article/grokking-concurrency/clojure/part-7.md +0 -99
  402. package/lib/assets/docs/article/grokking-concurrency/clojure/part-8.md +0 -119
  403. package/lib/assets/docs/article/grokking-concurrency/csharp/index.md +0 -91
  404. package/lib/assets/docs/article/grokking-concurrency/csharp/part-1.md +0 -96
  405. package/lib/assets/docs/article/grokking-concurrency/csharp/part-2.md +0 -122
  406. package/lib/assets/docs/article/grokking-concurrency/csharp/part-3.md +0 -100
  407. package/lib/assets/docs/article/grokking-concurrency/csharp/part-4.md +0 -111
  408. package/lib/assets/docs/article/grokking-concurrency/csharp/part-5.md +0 -98
  409. package/lib/assets/docs/article/grokking-concurrency/csharp/part-6.md +0 -60
  410. package/lib/assets/docs/article/grokking-concurrency/csharp/part-7.md +0 -83
  411. package/lib/assets/docs/article/grokking-concurrency/csharp/part-8.md +0 -91
  412. package/lib/assets/docs/article/grokking-concurrency/fsharp/index.md +0 -55
  413. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-1.md +0 -79
  414. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-2.md +0 -102
  415. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-3.md +0 -93
  416. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-4.md +0 -109
  417. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-5.md +0 -103
  418. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-6.md +0 -92
  419. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-7.md +0 -120
  420. package/lib/assets/docs/article/grokking-concurrency/fsharp/part-8.md +0 -106
  421. package/lib/assets/docs/article/grokking-concurrency/haskell/index.md +0 -238
  422. package/lib/assets/docs/article/grokking-concurrency/haskell/part-1.md +0 -95
  423. package/lib/assets/docs/article/grokking-concurrency/haskell/part-2.md +0 -95
  424. package/lib/assets/docs/article/grokking-concurrency/haskell/part-3.md +0 -90
  425. package/lib/assets/docs/article/grokking-concurrency/haskell/part-4.md +0 -105
  426. package/lib/assets/docs/article/grokking-concurrency/haskell/part-5.md +0 -98
  427. package/lib/assets/docs/article/grokking-concurrency/haskell/part-6.md +0 -94
  428. package/lib/assets/docs/article/grokking-concurrency/haskell/part-7.md +0 -110
  429. package/lib/assets/docs/article/grokking-concurrency/haskell/part-8.md +0 -117
  430. package/lib/assets/docs/article/grokking-concurrency/index.md +0 -66
  431. package/lib/assets/docs/article/grokking-concurrency/java/index.md +0 -92
  432. package/lib/assets/docs/article/grokking-concurrency/java/part-1.md +0 -307
  433. package/lib/assets/docs/article/grokking-concurrency/java/part-2.md +0 -333
  434. package/lib/assets/docs/article/grokking-concurrency/java/part-3.md +0 -220
  435. package/lib/assets/docs/article/grokking-concurrency/java/part-4.md +0 -212
  436. package/lib/assets/docs/article/grokking-concurrency/java/part-5.md +0 -111
  437. package/lib/assets/docs/article/grokking-concurrency/java/part-6.md +0 -68
  438. package/lib/assets/docs/article/grokking-concurrency/java/part-7.md +0 -100
  439. package/lib/assets/docs/article/grokking-concurrency/java/part-8.md +0 -100
  440. package/lib/assets/docs/article/grokking-concurrency/python/index.md +0 -303
  441. package/lib/assets/docs/article/grokking-concurrency/python/part-1.md +0 -238
  442. package/lib/assets/docs/article/grokking-concurrency/python/part-2.md +0 -417
  443. package/lib/assets/docs/article/grokking-concurrency/python/part-3.md +0 -226
  444. package/lib/assets/docs/article/grokking-concurrency/python/part-4.md +0 -298
  445. package/lib/assets/docs/article/grokking-concurrency/python/part-5.md +0 -314
  446. package/lib/assets/docs/article/grokking-concurrency/python/part-6.md +0 -296
  447. package/lib/assets/docs/article/grokking-concurrency/python/part-7.md +0 -313
  448. package/lib/assets/docs/article/grokking-concurrency/python/part-8.md +0 -359
  449. package/lib/assets/docs/article/grokking-concurrency/rust/index.md +0 -260
  450. package/lib/assets/docs/article/grokking-concurrency/rust/part-1.md +0 -107
  451. package/lib/assets/docs/article/grokking-concurrency/rust/part-2.md +0 -119
  452. package/lib/assets/docs/article/grokking-concurrency/rust/part-3.md +0 -125
  453. package/lib/assets/docs/article/grokking-concurrency/rust/part-4.md +0 -174
  454. package/lib/assets/docs/article/grokking-concurrency/rust/part-5.md +0 -157
  455. package/lib/assets/docs/article/grokking-concurrency/rust/part-6.md +0 -93
  456. package/lib/assets/docs/article/grokking-concurrency/rust/part-7.md +0 -132
  457. package/lib/assets/docs/article/grokking-concurrency/rust/part-8.md +0 -154
  458. package/lib/assets/docs/article/grokking-concurrency/scala/index.md +0 -59
  459. package/lib/assets/docs/article/grokking-concurrency/scala/part-1.md +0 -77
  460. package/lib/assets/docs/article/grokking-concurrency/scala/part-2.md +0 -111
  461. package/lib/assets/docs/article/grokking-concurrency/scala/part-3.md +0 -92
  462. package/lib/assets/docs/article/grokking-concurrency/scala/part-4.md +0 -109
  463. package/lib/assets/docs/article/grokking-concurrency/scala/part-5.md +0 -118
  464. package/lib/assets/docs/article/grokking-concurrency/scala/part-6.md +0 -82
  465. package/lib/assets/docs/article/grokking-concurrency/scala/part-7.md +0 -130
  466. package/lib/assets/docs/article/grokking-concurrency/scala/part-8.md +0 -128
  467. package/lib/assets/docs/article/grokkingfp/all/index.md +0 -368
  468. package/lib/assets/docs/article/grokkingfp/all/part-1-ch01-fp-introduction.md +0 -539
  469. package/lib/assets/docs/article/grokkingfp/all/part-1-ch02-pure-functions.md +0 -932
  470. package/lib/assets/docs/article/grokkingfp/all/part-2-ch03-immutable-data.md +0 -1137
  471. package/lib/assets/docs/article/grokkingfp/all/part-2-ch04-higher-order-functions.md +0 -1113
  472. package/lib/assets/docs/article/grokkingfp/all/part-2-ch05-flatmap.md +0 -1035
  473. package/lib/assets/docs/article/grokkingfp/all/part-3-ch06-option.md +0 -794
  474. package/lib/assets/docs/article/grokkingfp/all/part-3-ch07-either-adt.md +0 -880
  475. package/lib/assets/docs/article/grokkingfp/all/part-4-ch08-io-monad.md +0 -981
  476. package/lib/assets/docs/article/grokkingfp/all/part-4-ch09-streams.md +0 -935
  477. package/lib/assets/docs/article/grokkingfp/all/part-5-ch10-concurrency.md +0 -879
  478. package/lib/assets/docs/article/grokkingfp/all/part-6-ch11-application.md +0 -724
  479. package/lib/assets/docs/article/grokkingfp/all/part-6-ch12-testing.md +0 -635
  480. package/lib/assets/docs/article/grokkingfp/all/writing-plan.md +0 -721
  481. package/lib/assets/docs/article/grokkingfp/clojure/index.md +0 -276
  482. package/lib/assets/docs/article/grokkingfp/clojure/part-1.md +0 -676
  483. package/lib/assets/docs/article/grokkingfp/clojure/part-2.md +0 -652
  484. package/lib/assets/docs/article/grokkingfp/clojure/part-3.md +0 -629
  485. package/lib/assets/docs/article/grokkingfp/clojure/part-4.md +0 -706
  486. package/lib/assets/docs/article/grokkingfp/clojure/part-5.md +0 -760
  487. package/lib/assets/docs/article/grokkingfp/clojure/part-6.md +0 -730
  488. package/lib/assets/docs/article/grokkingfp/csharp/index.md +0 -246
  489. package/lib/assets/docs/article/grokkingfp/csharp/part-1.md +0 -820
  490. package/lib/assets/docs/article/grokkingfp/csharp/part-2.md +0 -980
  491. package/lib/assets/docs/article/grokkingfp/csharp/part-3.md +0 -990
  492. package/lib/assets/docs/article/grokkingfp/csharp/part-4.md +0 -958
  493. package/lib/assets/docs/article/grokkingfp/csharp/part-5.md +0 -956
  494. package/lib/assets/docs/article/grokkingfp/csharp/part-6.md +0 -748
  495. package/lib/assets/docs/article/grokkingfp/elixir/index.md +0 -203
  496. package/lib/assets/docs/article/grokkingfp/elixir/part-1.md +0 -721
  497. package/lib/assets/docs/article/grokkingfp/elixir/part-2.md +0 -847
  498. package/lib/assets/docs/article/grokkingfp/elixir/part-3.md +0 -994
  499. package/lib/assets/docs/article/grokkingfp/elixir/part-4.md +0 -983
  500. package/lib/assets/docs/article/grokkingfp/elixir/part-5.md +0 -1295
  501. package/lib/assets/docs/article/grokkingfp/elixir/part-6.md +0 -1058
  502. package/lib/assets/docs/article/grokkingfp/fsharp/index.md +0 -210
  503. package/lib/assets/docs/article/grokkingfp/fsharp/part-1.md +0 -723
  504. package/lib/assets/docs/article/grokkingfp/fsharp/part-2.md +0 -970
  505. package/lib/assets/docs/article/grokkingfp/fsharp/part-3.md +0 -981
  506. package/lib/assets/docs/article/grokkingfp/fsharp/part-4.md +0 -841
  507. package/lib/assets/docs/article/grokkingfp/fsharp/part-5.md +0 -920
  508. package/lib/assets/docs/article/grokkingfp/fsharp/part-6.md +0 -931
  509. package/lib/assets/docs/article/grokkingfp/haskell/index.md +0 -234
  510. package/lib/assets/docs/article/grokkingfp/haskell/part-1.md +0 -600
  511. package/lib/assets/docs/article/grokkingfp/haskell/part-2.md +0 -875
  512. package/lib/assets/docs/article/grokkingfp/haskell/part-3.md +0 -924
  513. package/lib/assets/docs/article/grokkingfp/haskell/part-4.md +0 -887
  514. package/lib/assets/docs/article/grokkingfp/haskell/part-5.md +0 -854
  515. package/lib/assets/docs/article/grokkingfp/haskell/part-6.md +0 -853
  516. package/lib/assets/docs/article/grokkingfp/index.md +0 -143
  517. package/lib/assets/docs/article/grokkingfp/java/index.md +0 -211
  518. package/lib/assets/docs/article/grokkingfp/java/part-1.md +0 -657
  519. package/lib/assets/docs/article/grokkingfp/java/part-2.md +0 -684
  520. package/lib/assets/docs/article/grokkingfp/java/part-3.md +0 -681
  521. package/lib/assets/docs/article/grokkingfp/java/part-4.md +0 -780
  522. package/lib/assets/docs/article/grokkingfp/java/part-5.md +0 -968
  523. package/lib/assets/docs/article/grokkingfp/java/part-6.md +0 -1337
  524. package/lib/assets/docs/article/grokkingfp/python/index.md +0 -258
  525. package/lib/assets/docs/article/grokkingfp/python/part-1.md +0 -452
  526. package/lib/assets/docs/article/grokkingfp/python/part-2.md +0 -967
  527. package/lib/assets/docs/article/grokkingfp/python/part-3.md +0 -1013
  528. package/lib/assets/docs/article/grokkingfp/python/part-4.md +0 -774
  529. package/lib/assets/docs/article/grokkingfp/python/part-5.md +0 -756
  530. package/lib/assets/docs/article/grokkingfp/python/part-6.md +0 -870
  531. package/lib/assets/docs/article/grokkingfp/ruby/index.md +0 -330
  532. package/lib/assets/docs/article/grokkingfp/ruby/part-1.md +0 -764
  533. package/lib/assets/docs/article/grokkingfp/ruby/part-2.md +0 -947
  534. package/lib/assets/docs/article/grokkingfp/ruby/part-3.md +0 -955
  535. package/lib/assets/docs/article/grokkingfp/ruby/part-4.md +0 -930
  536. package/lib/assets/docs/article/grokkingfp/ruby/part-5.md +0 -917
  537. package/lib/assets/docs/article/grokkingfp/ruby/part-6.md +0 -1421
  538. package/lib/assets/docs/article/grokkingfp/rust/index.md +0 -242
  539. package/lib/assets/docs/article/grokkingfp/rust/part-1.md +0 -643
  540. package/lib/assets/docs/article/grokkingfp/rust/part-2.md +0 -1069
  541. package/lib/assets/docs/article/grokkingfp/rust/part-3.md +0 -1003
  542. package/lib/assets/docs/article/grokkingfp/rust/part-4.md +0 -582
  543. package/lib/assets/docs/article/grokkingfp/rust/part-5.md +0 -714
  544. package/lib/assets/docs/article/grokkingfp/rust/part-6.md +0 -517
  545. package/lib/assets/docs/article/grokkingfp/scala/index.md +0 -171
  546. package/lib/assets/docs/article/grokkingfp/scala/part-1.md +0 -552
  547. package/lib/assets/docs/article/grokkingfp/scala/part-2.md +0 -955
  548. package/lib/assets/docs/article/grokkingfp/scala/part-3.md +0 -928
  549. package/lib/assets/docs/article/grokkingfp/scala/part-4.md +0 -751
  550. package/lib/assets/docs/article/grokkingfp/scala/part-5.md +0 -731
  551. package/lib/assets/docs/article/grokkingfp/scala/part-6.md +0 -876
  552. package/lib/assets/docs/article/grokkingfp/typescript/index.md +0 -273
  553. package/lib/assets/docs/article/grokkingfp/typescript/part-1.md +0 -570
  554. package/lib/assets/docs/article/grokkingfp/typescript/part-2.md +0 -1138
  555. package/lib/assets/docs/article/grokkingfp/typescript/part-3.md +0 -851
  556. package/lib/assets/docs/article/grokkingfp/typescript/part-4.md +0 -1096
  557. package/lib/assets/docs/article/grokkingfp/typescript/part-5.md +0 -726
  558. package/lib/assets/docs/article/grokkingfp/typescript/part-6.md +0 -991
  559. package/lib/assets/docs/article/practical-database-design/index.md +0 -121
  560. package/lib/assets/docs/article/practical-database-design/part1/chapter01.md +0 -297
  561. package/lib/assets/docs/article/practical-database-design/part1/chapter02.md +0 -527
  562. package/lib/assets/docs/article/practical-database-design/part1/chapter03.md +0 -566
  563. package/lib/assets/docs/article/practical-database-design/part2/chapter04.md +0 -933
  564. package/lib/assets/docs/article/practical-database-design/part2/chapter05.md +0 -1636
  565. package/lib/assets/docs/article/practical-database-design/part2/chapter06.md +0 -2725
  566. package/lib/assets/docs/article/practical-database-design/part2/chapter07.md +0 -2091
  567. package/lib/assets/docs/article/practical-database-design/part2/chapter08.md +0 -2114
  568. package/lib/assets/docs/article/practical-database-design/part2/chapter09.md +0 -2040
  569. package/lib/assets/docs/article/practical-database-design/part2/chapter10.md +0 -1396
  570. package/lib/assets/docs/article/practical-database-design/part2/chapter11.md +0 -1686
  571. package/lib/assets/docs/article/practical-database-design/part2/chapter12.md +0 -1426
  572. package/lib/assets/docs/article/practical-database-design/part2/chapter13.md +0 -1443
  573. package/lib/assets/docs/article/practical-database-design/part3/chapter14.md +0 -676
  574. package/lib/assets/docs/article/practical-database-design/part3/chapter15.md +0 -1634
  575. package/lib/assets/docs/article/practical-database-design/part3/chapter16.md +0 -1924
  576. package/lib/assets/docs/article/practical-database-design/part3/chapter17.md +0 -1717
  577. package/lib/assets/docs/article/practical-database-design/part3/chapter18.md +0 -2104
  578. package/lib/assets/docs/article/practical-database-design/part3/chapter19.md +0 -1132
  579. package/lib/assets/docs/article/practical-database-design/part3/chapter20.md +0 -1040
  580. package/lib/assets/docs/article/practical-database-design/part3/chapter21.md +0 -1391
  581. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter14-orm.md +0 -1000
  582. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter15-orm.md +0 -1309
  583. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter16-orm.md +0 -1175
  584. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter17-orm.md +0 -1593
  585. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter18-orm.md +0 -1192
  586. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter19-orm.md +0 -1025
  587. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter20-orm.md +0 -1762
  588. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter21-orm.md +0 -1456
  589. package/lib/assets/docs/article/practical-database-design/part3-orm/chapter22-orm.md +0 -1887
  590. package/lib/assets/docs/article/practical-database-design/part4/chapter22.md +0 -974
  591. package/lib/assets/docs/article/practical-database-design/part4/chapter23.md +0 -2078
  592. package/lib/assets/docs/article/practical-database-design/part4/chapter24.md +0 -2448
  593. package/lib/assets/docs/article/practical-database-design/part4/chapter25.md +0 -3670
  594. package/lib/assets/docs/article/practical-database-design/part4/chapter26.md +0 -2925
  595. package/lib/assets/docs/article/practical-database-design/part4/chapter27.md +0 -3114
  596. package/lib/assets/docs/article/practical-database-design/part4/chapter28.md +0 -2706
  597. package/lib/assets/docs/article/practical-database-design/part4/chapter29.md +0 -2552
  598. package/lib/assets/docs/article/practical-database-design/part4/chapter30.md +0 -2188
  599. package/lib/assets/docs/article/practical-database-design/part4/chapter31.md +0 -1200
  600. package/lib/assets/docs/article/practical-database-design/part4/chapter32.md +0 -2109
  601. package/lib/assets/docs/article/practical-database-design/part5/chapter33.md +0 -1041
  602. package/lib/assets/docs/article/practical-database-design/part5/chapter34.md +0 -1618
  603. package/lib/assets/docs/article/practical-database-design/part5/chapter35.md +0 -1462
  604. package/lib/assets/docs/article/practical-database-design/part5/chapter36.md +0 -1301
  605. package/lib/assets/docs/article/practical-database-design/part5/chapter37.md +0 -1479
  606. package/lib/assets/docs/article/practical-database-design/part5/chapter38.md +0 -1707
  607. package/lib/assets/docs/article/practical-database-design/part5/chapter39.md +0 -2343
  608. package/lib/assets/docs/article/practical-database-design/study/study2-1.md +0 -1702
  609. package/lib/assets/docs/article/practical-database-design/study/study2-2.md +0 -1356
  610. package/lib/assets/docs/article/practical-database-design/study/study2-3.md +0 -2053
  611. package/lib/assets/docs/article/practical-database-design/study/study2-4.md +0 -2238
  612. package/lib/assets/docs/article/practical-database-design/study/study2-5.md +0 -2427
  613. package/lib/assets/docs/article/practical-database-design/study/study3-1.md +0 -2214
  614. package/lib/assets/docs/article/practical-database-design/study/study3-2.md +0 -2230
  615. package/lib/assets/docs/article/practical-database-design/study/study3-3.md +0 -2262
  616. package/lib/assets/docs/article/practical-database-design/study/study3-4.md +0 -2115
  617. package/lib/assets/docs/article/practical-database-design/study/study3-5.md +0 -2516
  618. package/lib/assets/docs/article/practical-database-design/study/study4-1.md +0 -2596
  619. package/lib/assets/docs/article/practical-database-design/study/study4-2.md +0 -2084
  620. package/lib/assets/docs/article/practical-database-design/study/study4-3.md +0 -1814
  621. package/lib/assets/docs/article/practical-database-design/study/study4-4.md +0 -1904
  622. package/lib/assets/docs/article/practical-database-design/study/study4-5.md +0 -2887
@@ -1,1013 +0,0 @@
1
- ---
2
- type: Article
3
- title: "Part III: エラーハンドリングと型による安全性"
4
- description: "本章では、関数型プログラミングにおけるエラーハンドリングを学びます。"
5
- tags: [article, grokkingfp, python]
6
- status: stable
7
- generated: { by: human:kakimomokuri, at: 2026-03-24T05:22:28Z }
8
- ---
9
-
10
- # Part III: エラーハンドリングと型による安全性
11
-
12
- 本章では、関数型プログラミングにおけるエラーハンドリングを学びます。例外を使わず、型を使って安全にエラーを扱う方法を習得します。Python では `returns` ライブラリの `Maybe` と `Result` 型を使用します。
13
-
14
- ---
15
-
16
- ## 第6章: Maybe 型による安全なエラーハンドリング
17
-
18
- ### 6.1 なぜ Maybe が必要か
19
-
20
- 従来の Python コードでは、エラーを例外で処理します。しかし、例外は関数の戻り値の型に現れないため、呼び出し側が例外を処理し忘れる可能性があります。
21
-
22
- **ソースファイル**: `app/python/src/grokking_fp/ch06_option.py`
23
-
24
- ```python
25
- # 従来の方法(問題あり)- 例外を使う
26
- def unsafe_parse_int(s: str) -> int:
27
- return int(s) # ValueError が発生する可能性!
28
-
29
- # unsafe_parse_int("abc") # ValueError: invalid literal for int()
30
- ```
31
-
32
- ```plantuml
33
- @startuml
34
- !theme plain
35
-
36
- rectangle "従来の例外ベースのエラー処理" as ex {
37
- card "parse_int('42')" as ok
38
- card "42" as result_ok
39
- card "parse_int('abc')" as err
40
- card "ValueError!" as result_err
41
-
42
- ok --> result_ok : 成功
43
- err --> result_err : 例外発生
44
- }
45
-
46
- note bottom of result_err
47
- 例外は型に現れない
48
- 処理し忘れの危険
49
- end note
50
-
51
- @enduml
52
- ```
53
-
54
- ### 6.2 Maybe 型の基本
55
-
56
- `returns` ライブラリの `Maybe` 型を使うと、失敗の可能性を型で表現できます。
57
-
58
- ```python
59
- from returns.maybe import Maybe, Nothing, Some
60
-
61
- def parse_int(s: str) -> Maybe[int]:
62
- """文字列を整数に安全に変換する。"""
63
- try:
64
- return Some(int(s))
65
- except ValueError:
66
- return Nothing
67
-
68
- # 使用例
69
- assert parse_int("42") == Some(42) # 成功
70
- assert parse_int("abc") == Nothing # 失敗(エラーではない)
71
- ```
72
-
73
- ```plantuml
74
- @startuml
75
- !theme plain
76
-
77
- rectangle "Maybe 型によるエラー処理" {
78
- rectangle "Some(値)" as some {
79
- card "parse_int('42')" as s1
80
- card "Some(42)" as s2
81
- s1 --> s2 : 成功
82
- }
83
-
84
- rectangle "Nothing" as nothing {
85
- card "parse_int('abc')" as n1
86
- card "Nothing" as n2
87
- n1 --> n2 : 失敗
88
- }
89
- }
90
-
91
- note bottom
92
- 型を見れば失敗の可能性がわかる
93
- コンパイル時に処理を強制
94
- end note
95
-
96
- @enduml
97
- ```
98
-
99
- ### 6.3 TV番組のパース例
100
-
101
- **ソースファイル**: `app/python/src/grokking_fp/ch06_option.py`
102
-
103
- TV番組の文字列(例: `"Breaking Bad (2008-2013)"`)をパースする例で、Maybe の実践的な使い方を見てみましょう。
104
-
105
- ```python
106
- from dataclasses import dataclass
107
-
108
- @dataclass(frozen=True)
109
- class TvShow:
110
- """TV番組を表すイミュータブルなデータクラス。"""
111
- title: str
112
- start: int
113
- end: int
114
- ```
115
-
116
- #### 番組名を抽出
117
-
118
- ```python
119
- def extract_name(raw_show: str) -> Maybe[str]:
120
- """番組名を抽出する。"""
121
- bracket_open = raw_show.find("(")
122
- if bracket_open > 0:
123
- return Some(raw_show[:bracket_open].strip())
124
- return Nothing
125
-
126
- assert extract_name("Breaking Bad (2008-2013)") == Some("Breaking Bad")
127
- assert extract_name("(2008-2013)") == Nothing # 名前がない
128
- ```
129
-
130
- #### 開始年・終了年を抽出
131
-
132
- ```python
133
- def extract_year_start(raw_show: str) -> Maybe[int]:
134
- """開始年を抽出する。"""
135
- bracket_open = raw_show.find("(")
136
- dash = raw_show.find("-")
137
- if bracket_open != -1 and dash > bracket_open + 1:
138
- year_str = raw_show[bracket_open + 1 : dash]
139
- return parse_int(year_str)
140
- return Nothing
141
-
142
- def extract_year_end(raw_show: str) -> Maybe[int]:
143
- """終了年を抽出する。"""
144
- dash = raw_show.find("-")
145
- bracket_close = raw_show.find(")")
146
- if dash != -1 and bracket_close > dash + 1:
147
- year_str = raw_show[dash + 1 : bracket_close]
148
- return parse_int(year_str)
149
- return Nothing
150
- ```
151
-
152
- #### 単年の番組
153
-
154
- `"Chernobyl (2019)"` のような単年の番組もサポートします。
155
-
156
- ```python
157
- def extract_single_year(raw_show: str) -> Maybe[int]:
158
- """単年の番組から年を抽出する。"""
159
- dash = raw_show.find("-")
160
- bracket_open = raw_show.find("(")
161
- bracket_close = raw_show.find(")")
162
- if dash == -1 and bracket_open != -1 and bracket_close > bracket_open + 1:
163
- year_str = raw_show[bracket_open + 1 : bracket_close]
164
- return parse_int(year_str)
165
- return Nothing
166
-
167
- assert extract_single_year("Chernobyl (2019)") == Some(2019)
168
- assert extract_single_year("Breaking Bad (2008-2013)") == Nothing
169
- ```
170
-
171
- ### 6.4 Maybe の合成
172
-
173
- 複数の Maybe を組み合わせて処理するには、`bind` と `map` を使います。
174
-
175
- ```plantuml
176
- @startuml
177
- !theme plain
178
-
179
- rectangle "Maybe の操作" {
180
- rectangle "map" as mapOp {
181
- card "Some(5)" as m1
182
- card "map(lambda x: x * 2)" as m2
183
- card "Some(10)" as m3
184
- m1 --> m2
185
- m2 --> m3
186
- }
187
-
188
- rectangle "bind (flatMap)" as bindOp {
189
- card "Some(10)" as b1
190
- card "bind(safe_divide_by_2)" as b2
191
- card "Some(5)" as b3
192
- b1 --> b2
193
- b2 --> b3
194
- }
195
- }
196
-
197
- note bottom of mapOp
198
- map: 値を変換
199
- 関数は通常の値を返す
200
- end note
201
-
202
- note bottom of bindOp
203
- bind: Maybe を返す関数で変換
204
- ネストを防ぐ
205
- end note
206
-
207
- @enduml
208
- ```
209
-
210
- #### 文字列の加算
211
-
212
- ```python
213
- def add_strings(a: str, b: str) -> Maybe[int]:
214
- """2つの数値文字列を加算する。"""
215
- return parse_int(a).bind(lambda x: parse_int(b).map(lambda y: x + y))
216
-
217
- assert add_strings("10", "20") == Some(30)
218
- assert add_strings("10", "abc") == Nothing
219
- assert add_strings("abc", "20") == Nothing
220
- ```
221
-
222
- #### parse_show の完成
223
-
224
- ```python
225
- def parse_show(raw_show: str) -> Maybe[TvShow]:
226
- """TV番組の文字列をパースする。"""
227
- name = extract_name(raw_show)
228
- # lash: Nothing の場合に代替を試す(orElse に相当)
229
- year_start = extract_year_start(raw_show).lash(
230
- lambda _: extract_single_year(raw_show)
231
- )
232
- year_end = extract_year_end(raw_show).lash(
233
- lambda _: extract_single_year(raw_show)
234
- )
235
-
236
- return name.bind(
237
- lambda n: year_start.bind(
238
- lambda s: year_end.map(lambda e: TvShow(n, s, e))
239
- )
240
- )
241
-
242
- # 使用例
243
- assert parse_show("Breaking Bad (2008-2013)") == Some(TvShow("Breaking Bad", 2008, 2013))
244
- assert parse_show("Chernobyl (2019)") == Some(TvShow("Chernobyl", 2019, 2019))
245
- assert parse_show("Invalid") == Nothing
246
- ```
247
-
248
- ```plantuml
249
- @startuml
250
- !theme plain
251
-
252
- rectangle "parse_show のフロー" {
253
- card "Breaking Bad (2008-2013)" as input
254
-
255
- rectangle "抽出" {
256
- card "extract_name" as en
257
- card "extract_year_start" as eys
258
- card "extract_year_end" as eye
259
- }
260
-
261
- card "TvShow('Breaking Bad', 2008, 2013)" as result
262
-
263
- input --> en
264
- input --> eys
265
- input --> eye
266
- en --> result : bind
267
- eys --> result : bind
268
- eye --> result : map
269
- }
270
-
271
- @enduml
272
- ```
273
-
274
- ### 6.5 安全な操作
275
-
276
- **ソースファイル**: `app/python/src/grokking_fp/ch06_option.py`
277
-
278
- #### 安全な除算
279
-
280
- ```python
281
- def safe_divide(a: int, b: int) -> Maybe[int]:
282
- """安全な除算。"""
283
- if b == 0:
284
- return Nothing
285
- return Some(a // b)
286
-
287
- assert safe_divide(10, 2) == Some(5)
288
- assert safe_divide(10, 0) == Nothing
289
- ```
290
-
291
- #### 安全なリストアクセス
292
-
293
- ```python
294
- def safe_head(lst: list[T]) -> Maybe[T]:
295
- """リストの最初の要素を安全に取得する。"""
296
- if not lst:
297
- return Nothing
298
- return Some(lst[0])
299
-
300
- def safe_find(lst: list[T], predicate) -> Maybe[T]:
301
- """条件を満たす最初の要素を安全に見つける。"""
302
- for item in lst:
303
- if predicate(item):
304
- return Some(item)
305
- return Nothing
306
-
307
- assert safe_head([1, 2, 3]) == Some(1)
308
- assert safe_head([]) == Nothing
309
- assert safe_find([1, 2, 3, 4], lambda x: x > 2) == Some(3)
310
- ```
311
-
312
- ### 6.6 エラーハンドリング戦略
313
-
314
- 複数のパース処理を行う場合、2つの戦略があります。
315
-
316
- **ソースファイル**: `app/python/src/grokking_fp/ch06_option.py`
317
-
318
- #### Best-effort 戦略
319
-
320
- パースできたものだけ返す。
321
-
322
- ```python
323
- def parse_shows_best_effort(raw_shows: list[str]) -> list[TvShow]:
324
- """パースできたものだけ返す(Best-effort戦略)。"""
325
- results = []
326
- for raw in raw_shows:
327
- parsed = parse_show(raw)
328
- if isinstance(parsed, Some):
329
- results.append(parsed.unwrap())
330
- return results
331
-
332
- shows = ["Breaking Bad (2008-2013)", "Invalid", "Mad Men (2007-2015)"]
333
- result = parse_shows_best_effort(shows)
334
- assert len(result) == 2 # Invalid は無視される
335
- ```
336
-
337
- #### All-or-nothing 戦略
338
-
339
- 全部成功するか、全部失敗するか。
340
-
341
- ```python
342
- def parse_shows_all_or_nothing(raw_shows: list[str]) -> Maybe[list[TvShow]]:
343
- """全部成功するか、全部失敗するか(All-or-nothing戦略)。"""
344
- results: list[TvShow] = []
345
- for raw in raw_shows:
346
- parsed = parse_show(raw)
347
- if isinstance(parsed, Some):
348
- results.append(parsed.unwrap())
349
- else:
350
- return Nothing
351
- return Some(results)
352
-
353
- # 全て成功
354
- shows_ok = ["Breaking Bad (2008-2013)", "Mad Men (2007-2015)"]
355
- assert isinstance(parse_shows_all_or_nothing(shows_ok), Some)
356
-
357
- # 一つでも失敗すると Nothing
358
- shows_mixed = ["Breaking Bad (2008-2013)", "Invalid"]
359
- assert parse_shows_all_or_nothing(shows_mixed) == Nothing
360
- ```
361
-
362
- ```plantuml
363
- @startuml
364
- !theme plain
365
-
366
- rectangle "エラーハンドリング戦略" {
367
- rectangle "Best-effort" as be {
368
- card "['A', 'Invalid', 'B']" as be_input
369
- card "[TvShow('A'), TvShow('B')]" as be_output
370
- be_input --> be_output : 成功したものだけ
371
- }
372
-
373
- rectangle "All-or-nothing" as aon {
374
- card "['A', 'Invalid', 'B']" as aon_input
375
- card "Nothing" as aon_output
376
- aon_input --> aon_output : 一つでも失敗すると全て失敗
377
- }
378
- }
379
-
380
- @enduml
381
- ```
382
-
383
- ### 6.7 Maybe のユーティリティ
384
-
385
- **ソースファイル**: `app/python/src/grokking_fp/ch06_option.py`
386
-
387
- ```python
388
- # デフォルト値を取得
389
- def get_value_or_default(maybe: Maybe[int], default: int) -> int:
390
- return maybe.value_or(default)
391
-
392
- assert get_value_or_default(Some(42), 0) == 42
393
- assert get_value_or_default(Nothing, 0) == 0
394
-
395
- # 最初の Some を返す
396
- def first_some(maybes: list[Maybe[T]]) -> Maybe[T]:
397
- for m in maybes:
398
- if isinstance(m, Some):
399
- return m
400
- return Nothing
401
-
402
- assert first_some([Nothing, Nothing, Some(3), Some(4)]) == Some(3)
403
-
404
- # Some の値だけを抽出
405
- def filter_some(maybes: list[Maybe[T]]) -> list[T]:
406
- return [m.unwrap() for m in maybes if isinstance(m, Some)]
407
-
408
- assert filter_some([Some(1), Nothing, Some(3)]) == [1, 3]
409
-
410
- # 全ての Maybe が Some なら、値のリストを返す
411
- def sequence_maybes(maybes: list[Maybe[T]]) -> Maybe[list[T]]:
412
- results: list[T] = []
413
- for m in maybes:
414
- if isinstance(m, Some):
415
- results.append(m.unwrap())
416
- else:
417
- return Nothing
418
- return Some(results)
419
-
420
- assert sequence_maybes([Some(1), Some(2), Some(3)]) == Some([1, 2, 3])
421
- assert sequence_maybes([Some(1), Nothing, Some(3)]) == Nothing
422
- ```
423
-
424
- ---
425
-
426
- ## 第7章: Result 型と複合的なエラー処理
427
-
428
- ### 7.1 Maybe の限界
429
-
430
- `Maybe` は失敗を表現できますが、**なぜ失敗したか**を伝えることができません。
431
-
432
- ```python
433
- # Maybe では失敗理由がわからない
434
- assert parse_int("abc") == Nothing # なぜ失敗した?文字?空文字?
435
- ```
436
-
437
- ### 7.2 Result 型の基本
438
-
439
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
440
-
441
- `Result` 型を使うと、成功時は値を、失敗時はエラーメッセージを保持できます。
442
-
443
- ```python
444
- from returns.result import Result, Success, Failure
445
-
446
- def parse_int_result(s: str) -> Result[int, str]:
447
- """文字列を整数に変換し、エラーメッセージを返す。"""
448
- try:
449
- return Success(int(s))
450
- except ValueError:
451
- return Failure(f"Cannot parse '{s}' as integer")
452
-
453
- # 使用例
454
- assert parse_int_result("42") == Success(42)
455
- result = parse_int_result("abc")
456
- assert isinstance(result, Failure)
457
- assert "Cannot parse" in result.failure()
458
- ```
459
-
460
- ```plantuml
461
- @startuml
462
- !theme plain
463
-
464
- rectangle "Result 型" {
465
- rectangle "Success(値)" as success {
466
- card "parse_int_result('42')" as s1
467
- card "Success(42)" as s2
468
- s1 --> s2 : 成功
469
- }
470
-
471
- rectangle "Failure(エラー)" as failure {
472
- card "parse_int_result('abc')" as f1
473
- card "Failure('Cannot parse...')" as f2
474
- f1 --> f2 : 失敗
475
- }
476
- }
477
-
478
- note bottom of failure
479
- エラーの理由を保持
480
- デバッグが容易
481
- end note
482
-
483
- @enduml
484
- ```
485
-
486
- #### 安全な除算(エラーメッセージ付き)
487
-
488
- ```python
489
- def safe_divide_result(a: int, b: int) -> Result[int, str]:
490
- """安全な除算(エラーメッセージ付き)。"""
491
- if b == 0:
492
- return Failure("Division by zero")
493
- return Success(a // b)
494
-
495
- assert safe_divide_result(10, 2) == Success(5)
496
- assert safe_divide_result(10, 0) == Failure("Division by zero")
497
- ```
498
-
499
- ### 7.3 TV番組のパース(Result 版)
500
-
501
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
502
-
503
- ```python
504
- def extract_name_result(raw_show: str) -> Result[str, str]:
505
- """番組名を抽出する(エラーメッセージ付き)。"""
506
- bracket_open = raw_show.find("(")
507
- if bracket_open > 0:
508
- return Success(raw_show[:bracket_open].strip())
509
- return Failure(f"Can't extract name from '{raw_show}'")
510
-
511
- def extract_year_start_result(raw_show: str) -> Result[int, str]:
512
- """開始年を抽出する(エラーメッセージ付き)。"""
513
- bracket_open = raw_show.find("(")
514
- dash = raw_show.find("-")
515
- if bracket_open != -1 and dash > bracket_open + 1:
516
- year_str = raw_show[bracket_open + 1 : dash]
517
- return parse_int_result(year_str)
518
- return Failure(f"Can't extract start year from '{raw_show}'")
519
- ```
520
-
521
- ### 7.4 バリデーション
522
-
523
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
524
-
525
- Result 型はバリデーションに最適です。
526
-
527
- ```python
528
- def validate_age(age: int) -> Result[int, str]:
529
- """年齢を検証する。"""
530
- if age < 0:
531
- return Failure("Age cannot be negative")
532
- if age > 150:
533
- return Failure("Age cannot be greater than 150")
534
- return Success(age)
535
-
536
- def validate_email(email: str) -> Result[str, str]:
537
- """メールアドレスを検証する。"""
538
- if "@" not in email:
539
- return Failure("Email must contain '@'")
540
- if not email.endswith((".com", ".org", ".net", ".jp")):
541
- return Failure("Email must have a valid domain")
542
- return Success(email)
543
-
544
- def validate_password(password: str) -> Result[str, str]:
545
- """パスワードを検証する。"""
546
- if len(password) < 8:
547
- return Failure("Password must be at least 8 characters")
548
- if not any(c.isupper() for c in password):
549
- return Failure("Password must contain at least one uppercase letter")
550
- if not any(c.isdigit() for c in password):
551
- return Failure("Password must contain at least one digit")
552
- return Success(password)
553
- ```
554
-
555
- ```plantuml
556
- @startuml
557
- !theme plain
558
-
559
- rectangle "バリデーションチェーン" {
560
- card "validate_age(-5)" as v1
561
- card "Failure('Age cannot be negative')" as r1
562
-
563
- card "validate_email('invalid')" as v2
564
- card "Failure('Email must contain @')" as r2
565
-
566
- card "validate_password('SecurePass123')" as v3
567
- card "Success('SecurePass123')" as r3
568
-
569
- v1 --> r1
570
- v2 --> r2
571
- v3 --> r3
572
- }
573
-
574
- @enduml
575
- ```
576
-
577
- ### 7.5 代数的データ型(ADT)
578
-
579
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
580
-
581
- Python では `Enum` と `dataclass` を組み合わせて代数的データ型を表現します。
582
-
583
- ```python
584
- from enum import Enum, auto
585
-
586
- class MusicGenre(Enum):
587
- """音楽ジャンルを表す列挙型。"""
588
- HEAVY_METAL = auto()
589
- POP = auto()
590
- HARD_ROCK = auto()
591
- JAZZ = auto()
592
- CLASSICAL = auto()
593
-
594
- class Location(Enum):
595
- """場所を表す列挙型。"""
596
- US = "U.S."
597
- UK = "U.K."
598
- JAPAN = "Japan"
599
- GERMANY = "Germany"
600
-
601
- @dataclass(frozen=True)
602
- class PeriodInYears:
603
- """年の期間を表すデータクラス。"""
604
- start: int
605
- end: int | None # None はまだアクティブなことを示す
606
-
607
- @dataclass(frozen=True)
608
- class Artist:
609
- """アーティストを表すデータクラス。"""
610
- name: str
611
- genre: MusicGenre
612
- origin: Location
613
- years_active: PeriodInYears
614
- ```
615
-
616
- #### アーティストの活動判定
617
-
618
- ```python
619
- def was_artist_active(artist: Artist, year_start: int, year_end: int) -> bool:
620
- """アーティストが指定期間中にアクティブだったかを判定する。"""
621
- period = artist.years_active
622
- if period.end is None:
623
- # まだアクティブ
624
- return period.start <= year_end
625
- # 活動終了済み
626
- return period.start <= year_end and period.end >= year_start
627
-
628
- # 使用例
629
- metallica = Artist("Metallica", MusicGenre.HEAVY_METAL, Location.US, PeriodInYears(1981, None))
630
- assert was_artist_active(metallica, 2000, 2020) is True
631
- assert was_artist_active(metallica, 1970, 1975) is False
632
- ```
633
-
634
- ### 7.6 検索条件のモデリング
635
-
636
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
637
-
638
- Python 3.10+ のパターンマッチングを使って、検索条件を表現します。
639
-
640
- ```python
641
- @dataclass(frozen=True)
642
- class SearchByGenre:
643
- """ジャンルで検索する条件。"""
644
- genres: list[MusicGenre]
645
-
646
- @dataclass(frozen=True)
647
- class SearchByOrigin:
648
- """出身地で検索する条件。"""
649
- locations: list[Location]
650
-
651
- @dataclass(frozen=True)
652
- class SearchByActiveYears:
653
- """活動期間で検索する条件。"""
654
- start: int
655
- end: int
656
-
657
- # Union 型で検索条件を定義
658
- SearchCondition = SearchByGenre | SearchByOrigin | SearchByActiveYears
659
- ```
660
-
661
- #### パターンマッチングによる条件判定
662
-
663
- ```python
664
- def matches_condition(artist: Artist, condition: SearchCondition) -> bool:
665
- """アーティストが検索条件に一致するかを判定する。"""
666
- match condition:
667
- case SearchByGenre(genres):
668
- return artist.genre in genres
669
- case SearchByOrigin(locations):
670
- return artist.origin in locations
671
- case SearchByActiveYears(start, end):
672
- return was_artist_active(artist, start, end)
673
- ```
674
-
675
- ```plantuml
676
- @startuml
677
- !theme plain
678
-
679
- rectangle "パターンマッチング" {
680
- card "condition" as cond
681
-
682
- rectangle "match condition" as match {
683
- card "SearchByGenre(genres)" as g
684
- card "SearchByOrigin(locations)" as o
685
- card "SearchByActiveYears(start, end)" as y
686
- }
687
-
688
- cond --> match
689
- g --> "artist.genre in genres"
690
- o --> "artist.origin in locations"
691
- y --> "was_artist_active(...)"
692
- }
693
-
694
- @enduml
695
- ```
696
-
697
- #### 検索の実行
698
-
699
- ```python
700
- def search_artists(
701
- artists: list[Artist],
702
- required_conditions: list[SearchCondition],
703
- ) -> list[Artist]:
704
- """条件を全て満たすアーティストを検索する。"""
705
- return [
706
- artist
707
- for artist in artists
708
- if all(matches_condition(artist, cond) for cond in required_conditions)
709
- ]
710
-
711
- # 使用例
712
- metallica = Artist("Metallica", MusicGenre.HEAVY_METAL, Location.US, PeriodInYears(1981, None))
713
- queen = Artist("Queen", MusicGenre.HARD_ROCK, Location.UK, PeriodInYears(1970, 1995))
714
- artists = [metallica, queen]
715
-
716
- # ジャンルで検索
717
- result = search_artists(artists, [SearchByGenre([MusicGenre.HEAVY_METAL])])
718
- assert len(result) == 1
719
- assert result[0].name == "Metallica"
720
-
721
- # 複数条件で検索
722
- result = search_artists(artists, [
723
- SearchByGenre([MusicGenre.HARD_ROCK]),
724
- SearchByOrigin([Location.UK])
725
- ])
726
- assert result[0].name == "Queen"
727
- ```
728
-
729
- ### 7.7 Result の合成
730
-
731
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
732
-
733
- 複数のバリデーションを組み合わせてユーザーを作成します。
734
-
735
- ```python
736
- @dataclass(frozen=True)
737
- class User:
738
- """ユーザーを表すデータクラス。"""
739
- name: str
740
- email: str
741
- age: int
742
-
743
- def create_user(name: str, email: str, age: int) -> Result[User, str]:
744
- """ユーザーを作成する(バリデーション付き)。"""
745
- return validate_email(email).bind(
746
- lambda valid_email: validate_age(age).map(
747
- lambda valid_age: User(name, valid_email, valid_age)
748
- )
749
- )
750
-
751
- # 使用例
752
- assert create_user("Alice", "alice@example.com", 25) == Success(User("Alice", "alice@example.com", 25))
753
-
754
- result = create_user("Bob", "invalid", 25)
755
- assert isinstance(result, Failure)
756
- assert "Email must contain '@'" in result.failure()
757
- ```
758
-
759
- ### 7.8 型付きエラー
760
-
761
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
762
-
763
- 文字列の代わりに Enum を使うと、より型安全なエラー処理ができます。
764
-
765
- ```python
766
- class ValidationError(Enum):
767
- """バリデーションエラーの種類。"""
768
- EMPTY_NAME = "Name cannot be empty"
769
- INVALID_EMAIL = "Invalid email format"
770
- AGE_TOO_YOUNG = "Age must be at least 18"
771
- AGE_TOO_OLD = "Age cannot exceed 120"
772
-
773
- def validate_name_typed(name: str) -> Result[str, ValidationError]:
774
- """名前を検証する(型付きエラー)。"""
775
- if not name.strip():
776
- return Failure(ValidationError.EMPTY_NAME)
777
- return Success(name)
778
-
779
- def validate_age_typed(age: int) -> Result[int, ValidationError]:
780
- """年齢を検証する(型付きエラー)。"""
781
- if age < 18:
782
- return Failure(ValidationError.AGE_TOO_YOUNG)
783
- if age > 120:
784
- return Failure(ValidationError.AGE_TOO_OLD)
785
- return Success(age)
786
- ```
787
-
788
- ### 7.9 Result のユーティリティ
789
-
790
- **ソースファイル**: `app/python/src/grokking_fp/ch07_either.py`
791
-
792
- ```python
793
- from returns.maybe import Maybe, Some, Nothing
794
-
795
- def result_to_maybe(result: Result[T, str]) -> Maybe[T]:
796
- """Result を Maybe に変換する。"""
797
- if isinstance(result, Success):
798
- return Some(result.unwrap())
799
- return Nothing
800
-
801
- def get_or_else(result: Result[T, str], default: T) -> T:
802
- """Result から値を取得するか、デフォルト値を返す。"""
803
- if isinstance(result, Success):
804
- return result.unwrap()
805
- return default
806
-
807
- def map_error(result: Result[T, str], f) -> Result[T, str]:
808
- """エラーを変換する。"""
809
- if isinstance(result, Failure):
810
- return Failure(f(result.failure()))
811
- return result
812
-
813
- def sequence_results(results: list[Result[T, str]]) -> Result[list[T], str]:
814
- """全ての Result が Success なら、値のリストを返す。"""
815
- values: list[T] = []
816
- for r in results:
817
- if isinstance(r, Success):
818
- values.append(r.unwrap())
819
- else:
820
- return r
821
- return Success(values)
822
-
823
- # 使用例
824
- assert get_or_else(Success(42), 0) == 42
825
- assert get_or_else(Failure("error"), 0) == 0
826
-
827
- assert sequence_results([Success(1), Success(2)]) == Success([1, 2])
828
- assert sequence_results([Success(1), Failure("error")]) == Failure("error")
829
- ```
830
-
831
- ---
832
-
833
- ## まとめ
834
-
835
- ### Part III で学んだこと
836
-
837
- ```plantuml
838
- @startuml
839
- !theme plain
840
-
841
- rectangle "Part III: エラーハンドリングと型による安全性" {
842
- rectangle "第6章" as ch6 {
843
- card "Maybe 型"
844
- card "Some / Nothing"
845
- card "bind / map / lash"
846
- card "エラーハンドリング戦略"
847
- }
848
-
849
- rectangle "第7章" as ch7 {
850
- card "Result 型"
851
- card "Success / Failure"
852
- card "バリデーション"
853
- card "代数的データ型"
854
- card "パターンマッチング"
855
- }
856
- }
857
-
858
- ch6 --> ch7
859
-
860
- @enduml
861
- ```
862
-
863
- ### Maybe vs Result
864
-
865
- | 特徴 | Maybe | Result |
866
- |------|-------|--------|
867
- | 成功時 | `Some(値)` | `Success(値)` |
868
- | 失敗時 | `Nothing` | `Failure(エラー)` |
869
- | エラー情報 | なし | あり |
870
- | 用途 | 値がない可能性 | 失敗理由が必要 |
871
-
872
- ### キーポイント
873
-
874
- | 概念 | Python での実現方法 |
875
- |------|---------------------|
876
- | Maybe 型 | `returns.maybe.Maybe`, `Some`, `Nothing` |
877
- | Result 型 | `returns.result.Result`, `Success`, `Failure` |
878
- | 合成 | `bind`, `map`, `lash` |
879
- | ADT | `Enum`, `dataclass`, Union 型 |
880
- | パターンマッチング | `match`/`case` 文 |
881
-
882
- ### 重要な法則
883
-
884
- 1. **例外を避ける**: 型で失敗を表現する
885
- 2. **合成可能性**: `bind` と `map` でチェーン
886
- 3. **早期リターン**: 最初の失敗で処理を停止
887
- 4. **型による安全性**: コンパイル時にエラー処理を強制
888
-
889
- ### Python 特有のポイント
890
-
891
- - **`returns` ライブラリ**: `Maybe`, `Result` を提供
892
- - **`lash` メソッド**: `orElse` に相当(Nothing/Failure 時の代替)
893
- - **`bind` メソッド**: `flatMap` に相当
894
- - **パターンマッチング**: Python 3.10+ の `match`/`case`
895
- - **Union 型**: `|` で直和型を表現
896
-
897
- ---
898
-
899
- ## 演習問題
900
-
901
- ### 問題 1: Maybe を使った安全な辞書アクセス
902
-
903
- 辞書から安全に値を取得する関数を実装してください。
904
-
905
- ```python
906
- def safe_get(d: dict[str, T], key: str) -> Maybe[T]:
907
- ...
908
-
909
- # 期待される動作
910
- d = {"a": 1, "b": 2}
911
- assert safe_get(d, "a") == Some(1)
912
- assert safe_get(d, "c") == Nothing
913
- ```
914
-
915
- <details>
916
- <summary>解答</summary>
917
-
918
- ```python
919
- def safe_get(d: dict[str, T], key: str) -> Maybe[T]:
920
- if key in d:
921
- return Some(d[key])
922
- return Nothing
923
- ```
924
-
925
- </details>
926
-
927
- ### 問題 2: Result を使ったバリデーション
928
-
929
- ユーザー名のバリデーション関数を実装してください。
930
-
931
- ```python
932
- def validate_username(username: str) -> Result[str, str]:
933
- """
934
- - 空文字列: Failure("Username cannot be empty")
935
- - 3文字未満: Failure("Username must be at least 3 characters")
936
- - 20文字超: Failure("Username must be at most 20 characters")
937
- - それ以外: Success(username)
938
- """
939
- ...
940
- ```
941
-
942
- <details>
943
- <summary>解答</summary>
944
-
945
- ```python
946
- def validate_username(username: str) -> Result[str, str]:
947
- if not username:
948
- return Failure("Username cannot be empty")
949
- if len(username) < 3:
950
- return Failure("Username must be at least 3 characters")
951
- if len(username) > 20:
952
- return Failure("Username must be at most 20 characters")
953
- return Success(username)
954
- ```
955
-
956
- </details>
957
-
958
- ### 問題 3: 検索条件の追加
959
-
960
- 名前の部分一致で検索する条件を追加してください。
961
-
962
- ```python
963
- @dataclass(frozen=True)
964
- class SearchByName:
965
- """名前で検索する条件。"""
966
- name_contains: str
967
-
968
- # SearchCondition に追加
969
- SearchCondition = SearchByGenre | SearchByOrigin | SearchByActiveYears | SearchByName
970
- ```
971
-
972
- <details>
973
- <summary>解答</summary>
974
-
975
- ```python
976
- def matches_condition(artist: Artist, condition: SearchCondition) -> bool:
977
- match condition:
978
- case SearchByGenre(genres):
979
- return artist.genre in genres
980
- case SearchByOrigin(locations):
981
- return artist.origin in locations
982
- case SearchByActiveYears(start, end):
983
- return was_artist_active(artist, start, end)
984
- case SearchByName(name_contains):
985
- return name_contains.lower() in artist.name.lower()
986
- ```
987
-
988
- </details>
989
-
990
- ### 問題 4: sequence の実装
991
-
992
- `Maybe` のリストを `Maybe[list]` に変換する関数を、`bind` を使って実装してください。
993
-
994
- ```python
995
- def sequence_maybes_v2(maybes: list[Maybe[T]]) -> Maybe[list[T]]:
996
- """bind を使って sequence を実装する。"""
997
- ...
998
- ```
999
-
1000
- <details>
1001
- <summary>解答</summary>
1002
-
1003
- ```python
1004
- from functools import reduce
1005
-
1006
- def sequence_maybes_v2(maybes: list[Maybe[T]]) -> Maybe[list[T]]:
1007
- def append_if_some(acc: Maybe[list[T]], m: Maybe[T]) -> Maybe[list[T]]:
1008
- return acc.bind(lambda lst: m.map(lambda x: lst + [x]))
1009
-
1010
- return reduce(append_if_some, maybes, Some([]))
1011
- ```
1012
-
1013
- </details>