ããã«ã¡ã¯ååïŒ
ç°¡æœãªååf
æã€Pythonã®ã©ã€ãã©ãªã«ã€ããŠèª¬æããŸã ã ããã¯ãæ©èœçãªã¹ã¿ã€ã«ã§åé¡ã解決ããããã®é¢æ°ãšã¯ã©ã¹ãåããå°ããªããã±ãŒãžã§ãã
-äœãPythonçšã®å¥ã®æ©èœã©ã€ãã©ãªã§ããïŒ èè
ã¯ã fn.pyããããäžè¬ã«ãããã®æ©èœçãªã¯ã©ããã100äžåããããšãç¥ã£ãŠããŸããïŒ
-ã¯ããç¥ã£ãŠããŸãã
ã©ã€ãã©ãªã®å€èгã®çç±
ç§ã¯ããªãé·ãéPythonãç·Žç¿ããŠããŸããããæ°å¹Žåã颿°åããã°ã©ãã³ã°ãç¹ã«Klyuchã«çå£ã«å€¢äžã«ãªããŸããã FPã§æ¡çšãããããã€ãã®ã¢ãããŒãã¯ç§ã«éåžžã«åŒ·ãå°è±¡ãäžããã®ã§ãç§ã¯ããããæ¥åžžã®éçºã«ç§»ããããšæããŸããã
ããèšèªã®ãã¿ãŒã³ãå¥ã®èšèªã®ãã¿ãŒã³ã«å€§ãŸãã«åã蟌ãŸããŠããå Žåããã®ååãšã³ãŒãã£ã³ã°åæãèæ
®ããã«ã¢ãããŒããåãå
¥ããªãããšã匷調ããŸãã FPãã©ãã»ã©å¥œãã§ãã£ãŠãããããæ©èœçãªã¹ã¿ã€ã«ãšããŠæµãããšããããã«ã倧éã®ããããšã©ã ãã«æ©ãŸãããŠããŸãã
ãã®ãããååã®æµæã«åããªãããã«æ©èœãæŽããããšããŸããã ããšãã°ãFPã«ç²ŸéããŠããªã人ã®çè§£ãä¿é²ããããã«ãããããšãªãã¯ã·ã§ã³ã®ä»£ããã«æ¡ä»¶ä»ãã®æšæºãµã€ã¯ã«ã䜿çšããŸãã
ãã®çµæã峿žé€šã®äžéšã®éšåã¯æŠéãããžã§ã¯ãã«ãããããããã¯ãŸã 䜿çšäžã§ããã æåã«ããããããããžã§ã¯ããããããžã§ã¯ãã«ã³ããŒããæ¬¡ã«é¢æ°ãšã¹ããããã®ãã¡ã€ã«ãã³ããéå§ããæåŸã«ã©ã€ãã©ãªãPypiã®ããã±ãŒãžãããã³ããã¥ã¡ã³ãã§ãã¹ãŠãèšèšããŸããã
äžè¬çãªæ
å ±
ã©ã€ãã©ãªã¯çŽç²ãªPythonã§æžãããŠããã以äžãå«ããã¹ãŠã®OSã§åäœããŸã ãŽã£ã³ãã¥ã¹ã«ã Pythonã®äž¡æ¹ã®ãã©ã³ãããµããŒããããŠããŸãã å
·äœçã«ã¯ãããŒãžã§ã³2.6ã2.7ãããã³3.5ããã§ãã¯ããŸããã ä»ã®ããŒãžã§ã³ã§åé¡ãçºçããå Žåã¯ãç¥ãããã ããã å¯äžã®äŸåé¢ä¿ã¯ãäž¡æ¹ã®ãã©ã³ãã®ããäžã«ããã¢ãžã£ã€ã«éçºçšã®six
ããã±ãŒãžã§ãã
ã©ã€ãã©ãªã¯ãpipãä»ããŠæšæºçãªæ¹æ³ã§ã€ã³ã¹ããŒã«ãããŸãã
pip install f
ãã¹ãŠã®é¢æ°ãšã¯ã©ã¹ã¯ãheadã¢ãžã¥ãŒã«ã§å©çšã§ããŸãã ããã¯èŠããŠããå¿
èŠããªãããšãæå³ããŸã
ãšã³ãã£ãã£ãžã®ãã¹ïŒ
import f f.pcall(...) f.maybe(...) f.io_wraps(...) fL[1, 2, 3]
ããã±ãŒãžã«ã¯ã次ã®ãµãã·ã¹ãã ãæèŒãããŠããŸãã
- ããŒã¿ã䟿å©ã«åŠçããããã®ããŸããŸãªé¢æ°ã®ã»ãã
- æ¡ä»¶ããã°ãããã§ãã¯ããããã®è¿°èªã¢ãžã¥ãŒã«
- ã³ã¬ã¯ã·ã§ã³ã®æ¹è¯ããŒãžã§ã³-ãªã¹ããã¿ãã«ãèŸæžããã®ä»
- æ±çšå®è£
- Monadsãã¶ããã©ã¡ãããIOããšã©ãŒ
以äžã®ã»ã¯ã·ã§ã³ã§ã¯ãã³ã¡ã³ãä»ãã®ã³ãŒãäŸã瀺ããŸãã
æ©èœ
å¥ã®ãšã³ã·ã¹ãã ããPythonã«è»¢éããæåã®é¢æ°ã¯ãLuaèšèªããã®pcall
ã ç§ã¯æ°å¹Žåã«ããã°ã©ãã³ã°ããŸããããèšèªã¯æ©èœããŠããŸããããåãã§ããŸãã
pcallïŒä¿è·ãããåŒã³åºãïŒé¢æ°ã¯ãå¥ã®é¢æ°ãåãããã¢(err, result)
ãè¿ããŸããerrã¯ãšã©ãŒã§ã result
空ããŸãã¯ãã®éã§ãã JavascriptãGowãªã©ã®ä»ã®èšèªã§ã®ãã®ã¢ãããŒãã«ã¯ç²ŸéããŠããŸãã
import f f.pcall(lambda a, b: a / b, 4, 2) >>> (None, 2) f.pcall(lambda a, b: a / b, 4, 0) >>> (ZeroDivisionError('integer division or modulo by zero'), None)
ãã®é¢æ°ããäŸå€ãã¹ããŒããæ¢ã«èšè¿°ããã颿°ã®ãã³ã¬ãŒã¿ãŒãšããŠäœ¿çšãããšäŸ¿å©ã§ãã
@f.pcall_wraps def func(a, b): return a / b func(4, 2) >>> (None, 2) func(4, 0) >>> (ZeroDivisionError('integer division or modulo by zero'), None)
ç Žå£çãªæ§æã䜿çšãããšã眲åã¬ãã«ã§çµæãè§£åã§ããŸãã
def process((err, result)): if err: logger.exception(err) return 0 return result + 42 process(func(4, 2))
æ®å¿µãªãããç Žå£çãªæ§æã¯3çªç®ã®Pythonã§åé€ãããŠããŸãã æåã§è§£åããå¿
èŠããããŸãã
è峿·±ãããšã«ããã¢(err, result)
ã¯ã Either
ã¢ããã«ä»ãªããŸããã
以äžã¯ãããçŸå®çãªpcall
äŸã§ãã å€ãã®å ŽåãHTTPèŠæ±ãäœæãããžã§ã€ãœã³ããããŒã¿æ§é ãååŸããå¿
èŠããããŸãã ãªã¯ãšã¹ãäžã«å€ãã®ãšã©ãŒãçºçããå¯èœæ§ããããŸãã
- æ²ãã£ããã¹ãããªãŸã«ããŒãšã©ãŒ
- æ¥ç¶ã¿ã€ã ã¢ãŠã
- ãµãŒããŒã¯500ãè¿ããŸãã
- ãµãŒããŒã¯200ãè¿ããŸãããããžã§ã€ãœã³ã®è§£æã¯èœã¡ãŸãã
- ãµãŒããŒã¯200ãè¿ããŸããããçãã¯ãšã©ãŒã§ã
4ã€ã®äŸå€ããã£ããããŠtryã§åŒã³åºããã©ãããããšããããšã¯ãã³ãŒããå®å
šã«èªã¿åãäžå¯èœã«ããããšãæå³ããŸãã é
ããæ©ãããäœããååããã®ãå¿ããããã°ã©ã ãã¯ã©ãã·ã¥ããŸãã 以äžã¯ãã»ãŒå®éã®ã³ãŒãã®äŸã§ãã ããŒã«ã«ã¬ã¹ããµãŒãã¹ãããŠãŒã¶ãŒãååŸããŸãã çµæã¯åžžã«ãã¢ã«ãªããŸãã
@f.pcall_wraps def get_user(use_id): resp = requests.get("http://local.auth.server", params={"id": user_id}, timeout=3) if not resp.ok: raise IOError("<log HTTP code and body here>") data = resp.json() if "error" in data: raise BusinesException("<log here data>") return data
ä»ã®ã©ã€ãã©ãªé¢æ°ãæ€èšããŠãã ããã f.achain
ãšf.ichain
ã匷調ãf.achain
ãšf.ichain
ãŸãã ã©ã¡ããããã§ãŒã³å
ã®ãªããžã§ã¯ãããå®å
šã«ããŒã¿ãååŸããããã«èšèšãããŠããŸãã
次ã®ã¢ãã«ã®djangoããããšããŸãïŒ
Order => Office => Department => Chief
åæã«ããã¹ãŠã®ãã£ãŒã«ããnot null
ã¯not null
飿¥ãããã£ãŒã«ããå®å
šã«ç¢ºèªã§ããŸãã
order = Order.objects.get(id=42) boss_name = order.office.department.chief.name
ã¯ããç§ã¯select_related
ç¥ã£ãŠããŸãããããã¯åé¡ã§ã¯ãããŸããã ãã®ç¶æ³ã¯ãORMã ãã§ãªããä»ã®ã¯ã©ã¹æ§é ã«ãåœãŠã¯ãŸããŸãã
ãã顧客ãããã€ãã®ãªã³ã¯ã空ã«ããããšãèŠæ±ãããŸã§ãããã¯ç§ãã¡ã®ãããžã§ã¯ãã«ãããŸããããããã¯åœŒã®ããžãã¹ã®ç¹åŸŽã ããã§ãã ããŒã¿ããŒã¹å
ã®ãã£ãŒã«ããnullable
ãç°¡åã«éããããšãã§ããŠå¬ããã£ãã§ãã ãã¡ãããæ¥ãã®ããã«ã空ã®ãªã³ã¯ãæã€ã¢ãã«ã®åäœãã¹ããäœæããŸããã§ãããå€ããã¹ãã§ã¯ãã¢ãã«ã¯æ£ããå
¥åãããŠããŸããã ã¯ã©ã€ã¢ã³ãã¯æŽæ°ãããã¢ãã«ã§äœæ¥ãéå§ãããšã©ãŒãåãåããŸããã
f.achain
颿°ã¯ã屿§ãã§ãŒã³ãå®å
šã«èµ°æ»ããŸãã
f.achain(model, 'office', 'department', 'chief', 'name') >>> John
ãã§ãŒã³ãå£ããŠããå ŽåïŒãã£ãŒã«ããNoneãååšããªãïŒãçµæã¯Noneã«ãªããŸãã
f.ichain
ã¢ããã°f.ichain
ã¯ãäžé£ã®ã€ã³ããã¯ã¹ãå®è¡ããŸãã 圌女ã¯èŸæžããªã¹ããããã³ã¿ãã«ã䜿çšããŸãã ãã®é¢æ°ã¯ãjasonããååŸããããŒã¿ãæäœããã®ã«äŸ¿å©ã§ãã
data = json.loads('''{"result": [{"kids": [{"age": 7, "name": "Leo"}, {"age": 1, "name": "Ann"}], "name": "Ivan"}, {"kids": null, "name": "Juan"}]}''') f.ichain(data, 'result', 0, 'kids', 0, 'age') >>> 7 f.ichain(data, 'result', 0, 'kids', 42, 'dunno') >> None
ç§ã¯äž¡æ¹ã®æ©èœãã¯ã©ããããget-in
ãã¯ã©ããã®ç¥å
ã¯get-in
ãšåŒã°get-in
ãŸãã 䟿å©ãªç¹ã¯ããã€ã¯ããµãŒããŒã¢ãŒããã¯ãã£ã§ã¯ãå¿çã®æ§é ãçµ¶ããå€åããŠãããåžžèã«å¯Ÿå¿ããŠããªãå Žåãããããšã§ãã
ããšãã°ãå¿çã«ã¯ããã¹ãããããã£ãŒã«ããæã€ãŠãŒã¶ãŒãªããžã§ã¯ããã£ãŒã«ãããããŸãã ãã ããäœããã®çç±ã§ãŠãŒã¶ãŒãããªãå Žåããã£ãŒã«ãã¯ç©ºã®ãªããžã§ã¯ãã§ã¯ãªãããªãã«ãªããŸãã æ¬¡ã®ãããªUãæ§é ïŒ
data.get('user', {]}).get('address', {}).get('street', '<unknown>')
ç§ãã¡ã®ããŒãžã§ã³ã¯èªã¿ãããã§ãïŒ
f.ichain(data, 'user', 'address', 'street') or '<unknown>'
Kluzhaããã©ã€ãã©ãªf
æž¡ããã2ã€ã®ã¹ã¬ãããã¯ãïŒ ->
ããã³->>
ã ã©ã€ãã©ãªã§ã¯ããããã¯f.arr1
ããã³f.arr2
ãšåŒã°ããŸãã äž¡æ¹ãšããåæå€ã颿°åœ¢åŒã«æž¡ããŸã ã Lispã®ãã®çšèªã¯ãåŸã§èšç®ãããåŒãæå³ããŸãã
èšãæããã°ã ãã©ãŒã ã¯func
颿°ãŸãã¯ãã©ãŒã ã®ã¿ãã«(func, arg1, arg2, ...)
ãããã(func, arg1, arg2, ...)
ã ãã®ãã©ãŒã ã¯ãåçµåŒã®ãããªå Žæã«æž¡ããŠãåŸã§å€æŽããŠèšç®ã§ããŸãã Lispã®ãã¯ãã®ãããªãã®ã倿ããŸãããéåžžã«æ²æšã§ãã
f.arr1
ã¯å€ïŒããã³ããã«çµæïŒãæåã®å€f.arr1
眮ãæããŸã
ãã©ãŒã åŒæ°ïŒ
f.arr1( -42,
f.arr2
ã¯åãããšãè¡ããŸãããå€ããã©ãŒã ã®æåŸã«f.arr2
ããŸãã
f.arr2( -2, abs, (lambda a, b: a + b, 2), str, ("000".replace, "0") ) >>> "444"
次ã«ã f.comp
颿°ã¯é¢æ°ã®æ§æãè¿ããŸãã
comp = f.comp(abs, (lambda x: x * 2), str) comp(-42) >>> "84"
f.every_pred
ã¯ã¹ãŒããŒè¿°èªãæ§ç¯ããŸãã ããã¯ããã¹ãŠã®å
éšè¿°èªãçã§ããå Žåã«ã®ã¿çãšãªãè¿°èªã§ãã
pred1 = f.p_gt(0)
ã¹ãŒããŒè¿°èªã¯æ laã§ããæåã®åœã®å€ã§èšç®ã®é£éãäžæããŸãã äžèšã®äŸã§ã¯ã predicate.py
ã¢ãžã¥ãŒã«ã®predicate.py
ã䜿çšãããŠããŸããããã«ã€ããŠã¯åŸã§èª¬æããŸãã
f.transduce
颿°ã¯ãClaudeã®ãã©ã³ã¹ãã¥ãŒãµãŒïŒãã©ã³ã¹ãã©ãŒããŒïŒãã¿ãŒã³ãå®è£
ããããšããçŽ æŽãªè©Šã¿ã§ãã èŠããã«ã transducer
ã¯map
æ©èœãšreduce
æ©èœã®çµã¿åããã§ãã ãããã®éãåããã«ããããäžéããŒã¿ã®ãªããã®ãããããããã®ãžããšããååã«åŸã£ãŠå€æãè¡ãããŸãã
f.transduce( (lambda x: x + 1), (lambda res, item: res + str(item)), (1, 2, 3), "" ) >>> "234"
颿°ã®ã¢ãžã¥ãŒã«f.nth f.nth
ãšãã®å矩èªïŒã³ã¬ã¯ã·ã§ã³èŠçŽ ãžã®å®å
šãªã¢ã¯ã»ã¹ã®ããã®f.first
ã f.second
ããã³f.third
ïŒ
f.first((1, 2, 3)) >>> 1 f.second((1, 2, 3)) >>> 2 f.third((1, 2, 3)) >>> 3 f.nth(0, [1, 2, 3]) >>> 1 f.nth(9, [1, 2, 3]) >>> None
è¿°èª
ã¯ãtrueãŸãã¯falseãè¿ãåŒã§ãã è¿°èªã¯ãæ°åŠãè«çãããã³é¢æ°åããã°ã©ãã³ã°ã§äœ¿çšãããŸãã å€ãã®å Žåãè¿°èªã¯é«é颿°ã®å€æ°ãšããŠæž¡ãããŸãã
ã©ã€ãã©ãªã«æãå¿
èŠãªè¿°èªã®ããã€ãã远å ããŸããã è¿°éšã®åäœãæåã®åŒæ°ã«äŸåããå Žåãè¿°éšã¯åé
ïŒãã©ã¡ãŒã¿ãŒãªãïŒããã³äºé
ïŒãŸãã¯ãã©ã¡ããªãã¯ïŒã«ãªããŸãã
åé
è¿°èªã䜿çšããäŸãæ€èšããŠãã ããã
f.p_str("test") >>> True f.p_str(0) >>> False f.p_str(u"test") >>> True
ãã€ããªã«ãªããŸããã äœãããŒããã倧ãããšäž»åŒµããæ°ããè¿°èªãäœæããŸãã ãã£ããäœïŒ ãŸã ç¥ãããŠããªããããã¯æœè±¡åã§ãã
p = f.p_gt(0)
次ã«ãè¿°èªã䜿çšããŠãä»»æã®å€ã確èªããŸãã
p(1), p(100), p(0), p(-1) >>> True, True, False, False
顿šã«ãã£ãŠïŒ
ãã¹ãŠã®è¿°èªã®äŸã¯ç€ºããŸããããããã¯éå±ã§é·ããªããŸãã è¿°èªã¯ãåæé¢æ°f.comp
ãã¹ãŒããŒè¿°èªf.every_pred
ãçµã¿èŸŒã¿filter
颿°ãããã³ä»¥äžã§èª¬æããæ±çšf.every_pred
ãšå®å
šã«f.comp
ãŸãã
ãžã§ããªãã¯
ãžã§ããªãã¯ïŒgeneralãgeneralizedïŒã¯ãçµæãèšç®ããããã®ããã€ãã®æŠç¥ãæã€ãåŒã³åºããããªããžã§ã¯ãã§ãã æŠç¥ã®éžæã¯ãå
¥åãã©ã¡ãŒã¿ãŒïŒæ§æãã¿ã€ãããŸãã¯å€ïŒã«åºã¥ããŠæ±ºå®ãããŸãã ãžã§ããªãã¯ã¯ãæž¡ããããã©ã¡ãŒã¿ãŒã«å¯ŸããŠä»ã«èŠã€ãããªãå Žåãããã©ã«ãæŠç¥ã®ååšãæ³å®ããŸãã
Pythonã§ã¯ãããã«äœ¿çšã§ãããžã§ããªãã¯ã¯ãªããç¹ã«å¿
èŠãããŸããã Pythonã¯ãå
¥åå€ã®é¢æ°ãéžæããç¬èªã®ã·ã¹ãã ãæ§ç¯ããã®ã«ååãªæè»æ§ãåããŠããŸãã ããã§ããCommon Lispã§ã®ãžã§ããªãã¯ã®å®è£
ãéåžžã«å¥œãã ã£ãã®ã§ãã¹ããŒãã®é¢å¿ããã©ã€ãã©ãªã§åæ§ã®ããšãããããšã«ããŸããã
ãããªæãã§ãã ãŸãããžã§ããªãã¯ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸãã
gen = f.Generic()
次ã«ãç¹å®ã®ãã³ãã©ãŒã§æ¡åŒµããŸãã .extend
ãã³ã¬ãŒã¿ã¯ããã®ãã³ãã©ãŒã®äžé£ã®è¿°èªãåŒæ°ããšã«1ã€åãåããŸãã
@gen.extend(f.p_int, f.p_str) def handler1(x, y): return str(x) + y @gen.extend(f.p_int, f.p_int) def handler2(x, y): return x + y @gen.extend(f.p_str, f.p_str) def handler3(x, y): return x + y + x + y @gen.extend(f.p_str) def handler4(x): return "-".join(reversed(x)) @gen.extend() def handler5(): return 42
å
éšã®ããžãã¯ã¯åçŽã§ãããã³ã¬ãŒã¿ã¯ãå²ãåœãŠãããè¿°èªãšãšãã«é¢æ°ãå
éšèŸæžã«ãã¡ã€ã«ããŸãã ããã§ããžã§ããªãã¯ã¯ä»»æã®åŒæ°ã§åŒã³åºãããšãã§ããŸãã åŒã³åºããããšã颿°ã¯åãæ°ã®äºæž¬åã§æ€çŽ¢ãããŸãã åè¿°èªã察å¿ããåŒæ°ã«å¯ŸããŠtrueãè¿ãå ŽåãæŠç¥ãèŠã€ãã£ããšèŠãªãããŸãã èŠã€ãã£ã颿°ãåŒã³åºããçµæãè¿ãããŸãïŒ
gen(1, "2") >>> "12" gen(1, 2) >>> 3 gen("fiz", "baz") >>> "fizbazfizbaz" gen("hello") >>> "olleh" gen() >>> 42
æŠç¥ãåºãªãå Žåã¯ã©ããªããŸããïŒ ããã©ã«ãã®ãã³ãã©ãŒãèšå®ãããŠãããã©ããã«ãã£ãŠç°ãªããŸãã ãã®ãããªãã³ãã©ãŒã¯ãä»»æã®æ°ã®åŒæ°ãæºããæºåãã§ããŠããå¿
èŠããããŸãã
gen(1, 2, 3, 4) >>> TypeError exception goes here... @gen.default def default_handler(*args): return "default" gen(1, 2, 3, 4) >>> "default"
è£
食åŸã颿°ã¯ãžã§ããªãã¯ã®ã€ã³ã¹ã¿ã³ã¹ã«ãªããŸãã è峿·±ãããªãã¯ã¯ãããæŠç¥ã®å®è¡ãå¥ã®æŠç¥ã«ç§»ãããšãã§ãããšããããšã§ãã ClaudeãErlangãHaskellã®ããã«ãããã€ãã®ããã£ã§æ©èœããããšãããããŸãã
None
ãæž¡ããšã以äžã®ãã³ãã©ãŒãåŒã³åºãããŸãã ãã ããå
éšã§ã¯2ã€ã®intãæã€å¥ã®ãã³ãã©ãŒã«ãªãã€ã¬ã¯ããããŸããããã¯handler2
ã§ãã ããã«ãããåŒæ°ã®åèšãè¿ãããŸãã
@gen.extend(f.p_none) def handler6(x): return gen(1, 2) gen(None) >>> 3
ã³ã¬ã¯ã·ã§ã³
ãã®ã©ã€ãã©ãªã¯ããªã¹ããã¿ãã«ãèŸæžãããã³ã»ããã«åºã¥ããã匷åããããã³ã¬ã¯ã·ã§ã³ãæäŸããŸãã æ¹åãšã¯ãåã³ã¬ã¯ã·ã§ã³ã®åäœã«ããã远å ã®ã¡ãœãããšããã€ãã®æ©èœãæå³ããŸãã
æ¹åãããã³ã¬ã¯ã·ã§ã³ã¯ãã¯ã©ã¹ãåŒã³åºãããšã«ãã£ãŠéåžžã®ã³ã¬ã¯ã·ã§ã³ããäœæãããããè§æ¬åŒ§ã§å²ãŸããç¹å¥ãªæ§æã«ãã£ãŠäœæãããŸãã
fL[1, 2, 3]
ã³ã¬ã¯ã·ã§ã³ã«ã¯ã .join
ã .foreach
ã .map
ã .filter
ã .reduce
ã .sum
ãŸãã
ãªã¹ããšã¿ãã«ã¯ãããã«.reversed
ã .sorted
ã .group
ã .distinct
ããã³.apply
ãŸãã
ã¡ãœããã䜿çšãããšã颿°ã«æž¡ããã«ã³ã¬ã¯ã·ã§ã³ããçµæãååŸã§ããŸãã
l1 = fL[1, 2, 3] l1.map(str).join("-") >>> "1-2-3"
result = [] def collect(x, delta=0): result.append(x + delta) l1.foreach(collect, delta=1) result == [2, 3, 4] >>> True
l1.group(2) >>> List[List[1, 2], List[3]]
ç§ã¯åã¡ãœããã®ãªã¹ããéå±ãããŸãããåžæãã人ã¯ã³ã¡ã³ãä»ãã§ãœãŒã¹ã³ãŒããèŠãããšãã§ããŸãã
ã¡ãœãããåãã³ã¬ã¯ã·ã§ã³ã®æ°ããã€ã³ã¹ã¿ã³ã¹ãè¿ãããšãéèŠã§ãã ããã«ããã圌女ã誀ã£ãŠå€ããå¯èœæ§ãäœããªããŸãã æäœ.map
ãŸãã¯ãªã¹ãã®ä»ã®æäœã¯ããªã¹ããã¿ãã«ãã¿ãã«ãªã©ãè¿ããŸãã
fL[1, 2, 3].filter(f.p_even) >>> List[2]
fS[1, 2, 3].filter(f.p_even) >>> Set{2}
èŸæžã¯ãç§ããã€ã倢èŠãŠãããã¢(, )
å埩åŠçã(, )
ã
fD[1: 1, 2: 2, 0: 2].filter(lambda (k, v): k + v == 2) >>> Dict{0: 2, 1: 1}
æ¹åãããã³ã¬ã¯ã·ã§ã³ã¯ãä»ã®ã³ã¬ã¯ã·ã§ã³ãšç©ã¿éããããšãã§ããŸãã çµæã¯ããã®ïŒå·ŠïŒã¿ã€ãã®æ°ããã³ã¬ã¯ã·ã§ã³ã«ãªããŸãã
ã©ã®ã³ã¬ã¯ã·ã§ã³ãå¥ã®ã³ã¬ã¯ã·ã§ã³ã«åãæ¿ããããšãã§ããŸãã
fL["a", 1, "b", 2].group(2).D() >>> Dict{"a": 1, "b": 2} fL[1, 2, 3, 3, 2, 1].S().T() >>> Tuple[1, 2, 3]
ã³ã³ãïŒ
fL("abc").map(ord).map(str).reversed().join("-") >>> "99-98-97"
def pred(pair): k, v = pair return k == "1" and v == "2" fL[4, 3, 2, 1].map(str).reversed() \ .group(2).Dict().filter(pred) >>> Dict{"1": "2"}
ã¢ãã
ã©ã€ãã©ãªã®æåŸã§æãé£ããã»ã¯ã·ã§ã³ã ã¢ããã«é¢ããäžé£ã®èšäºãèªãã åŸãç§ãããããã©ã€ãã©ãªã«è¿œå ããããšæããŸããã åæã«ãåœŒã¯æ¬¡ã®éžè±ãèš±å¯ããŸããã
å
¥åå€ã®ãã§ãã¯ã¯ãHaskellã®ãããªåã§ã¯ãªããè¿°èªã«åºã¥ããŠãããããã¢ãããããæè»ã«ãªããŸãã
Haskellã®>>=
æŒç®åã¯Pythonã«è»¢éã§ããªãããã >>
ïŒå¥å__rshift__
ãå³ãžã®ãããã·ããïŒãšããŠè¡šç€ºãããŸãã åé¡ã¯ãHaskellã«ã>>
æŒç®åããããŸããã >>=
ããã䜿çšé »åºŠãäœãããšã§ãã çµæãšããŠãPythonã§ã¯>>
ãæå³ããHaskellãã>>=
ãæå³ããŸãããå
ã®>>
ã¯äœ¿çšããŸããã
- åªåã«ãããããããPythonã®æ§æã®å¶éã®ããã«Haskellã®doèšæ³ãå®è£
ã§ããŸããã§ããã ãµã€ã¯ã«ããžã§ãã¬ãŒã¿ãŒãã³ã³ããã¹ããããŒãžã£ãŒã詊ããŸããã
ãã¶ã
ãã¶ããã¢ããã¯ãªãã·ã§ã³ãšããŠãç¥ãããŠããŸãã ãã®ã¯ã©ã¹ã®ã¢ããã¯ã2ã€ã®ã€ã³ã¹ã¿ã³ã¹ã§è¡šãããŸããJust ïŒãŸãã¯SomeïŒã¯ãèå³ã®ããè¯å®çãªçµæã®ãªããžããªã§ãã äœãïŒä»ã®èšèªã§ã¯-ãªãïŒ -空ã®çµæã
ç°¡åãªäŸã ã¢ããã³ã³ã¹ãã©ã¯ã¿ãŒãå®çŸ©ãã- ã¹ã«ã©ãŒïŒãã©ããïŒå€ãã¢ããã«å€æãããªããžã§ã¯ãïŒ
MaybeInt = f.maybe(f.p_int)
å¥ã®æ¹æ³ã§ã¯ã unit ããŸãã¯ã¢ãããŠããããšåŒã°ããŸãã ã¢ããå€ãååŸããŸãïŒ
MaybeInt(2) >>> Just[2] MaybeInt("not an int") >>> Nothing
è¯ãçµæã«ãªãã®ã¯ãintã®ãã¹ãã«åæ Œããããšã ãã§ãã ããã§ã¯ã ã¢ãããã€ãã©ã€ã³ãå®éã«è©ŠããŠã¿ãŸãããã
MaybeInt(2) >> (lambda x: MaybeInt(x + 2)) >>> Just[4] MaybeInt(2) >> (lambda x: f.Nothing()) >> (lambda x: MaybeInt(x + 2)) >>> Nothing
äŸãããããããã«ã Nothing
ãã§ãŒã³ã®å®è¡ãäžæãNothing
ã å®å
šã«æ£ç¢ºã«èšããšããã§ãŒã³ã¯éåãããæåŸãŸã§é²ã¿ãåã¹ãããã§Nothing
è¿ããNothing
ã
ã¢ãããã³ã¬ãŒã¿ã§ä»»æã®é¢æ°ãã«ããŒããŠãããããã¹ã«ã©ãŒã®ã¢ãã衚çŸãååŸã§ããŸãã 以äžã®äŸã§ã¯ããã³ã¬ãŒã¿ãŒã¯ãæ»ãå€ã®intã®ã¿ãæåãšèŠãªãããããã«ããŸãããã®å€ã¯Just
ãä»ã®ãã¹ãŠã¯Nothing
ãŸãã
@f.maybe_wraps(f.p_num) def mdiv(a, b): if b: return a / b else: return None mdiv(4, 2) >>> Just[2] mdiv(4, 0) >>> Nothing
>>
æŒç®åã¯ã ã¢ãããã€ã³ãã£ã³ã°ãšãåŒã°ãã .bind
ã¡ãœããã«ãã£ãŠåŒã³åºãããŸãã
MaybeInt(2).bind(lambda x: MaybeInt(x + 1)) >>> Just[3]
>>
ãš.bind
ã¡ãœããã¯ã颿°ã ãã§ãªãã 颿°ã®åœ¢ããšãããšãã§ããŸãã
MaybeInt(6) >> (mdiv, 2) >>> Just[3] MaybeInt(6).bind(mdiv, 2) >>> Just[3]
ã¢ããããã¹ã«ã©ãŒå€ãè§£æŸããã«ã¯ã .get
ã¡ãœããã䜿çšããŸãã ã¢ããã®å€å
žçãªå®çŸ©ã«ã¯å«ãŸããŠããããäžçš®ã®inã§ããããšã«æ³šæããããšãéèŠã§ãã .get
ã¡ãœããã¯ãå³å¯ã«ãã€ãã©ã€ã³ã®æåŸã«ããå¿
èŠããããŸãã
m = MaybeInt(2) >> (lambda x: MaybeInt(x + 2)) m.get() >>> 3
ã©ã¡ãã
ãã®ã¢ããã¯åã®ãã®ãæ¡åŒµããŸãã ãã¶ãåé¡ã¯åŠå®çãªçµæãç Žæ£ãããããšã§ãããç§ãã¡ã¯åžžã«çç±ãç¥ãããã§ãã ã©ã¡ãããå·Šãšå³ãå·Šãšå³ã®å€ã®ãµãã¿ã€ãã§æ§æãããŸãã å·Šã®å€ã¯è² ã®ã±ãŒã¹ãæ
åœããå³ã®å€ã¯æ£ã®ã±ãŒã¹ãæ
åœããŸãã
ãã®ã«ãŒã«ã¯ããç§ãã¡ã®åå ã¯æ£ããïŒã€ãŸããçïŒããšãããã¬ãŒãºã§èŠããããã§ãã è±èªã®æ£ããèšèã¯ãå¿ å®ããæå³ããŸãã
ãããŠãããã«éå»ããã®ãã©ãã·ã¥ããã¯ããããŸãïŒåæããŠãããã¯èšäºã®åé ããã«ããã«(err, result)
ãæãåºãããŸããïŒ Javascriptã§ã®ã³ãŒã«ããã¯ïŒ Gowã®åŒã³åºãçµæïŒç°ãªãé åºã§ã®ã¿ïŒïŒ
ããã¯åãã§ãã ãããã¯ãã¹ãŠã¢ããã§ãããã³ã³ãããæ°åŠçãªè£
眮ãªãã§ã¯è£
食ãããŠããŸããã
Either
ã¢ããã¯ãäž»ã«ãšã©ãŒããã£ããããããã«äœ¿çšãããŸãã 誀ã£ãå€ã¯å·Šã«é²ã¿ãçµç«ã©ã€ã³ã®çµæã«ãªããŸãã æ£ããçµæã¯ã次ã®èšç®ã®ããã«å³åŽã«ã¹ã¯ã©ã³ãã«ãããŸãã
Bothã¢ããã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãå·Šã®å€ãšå³ã®2ã€ã®è¿°èªãåãå
¥ããŸãã 以äžã®äŸã§ã¯ãæååå€ã¯å·Šã®å€ã«ãæ°å€ã¯å³ã«ç§»åããŸãã
EitherStrNum = f.either(f.p_str, f.p_num) EitherStrNum("error") >>> Left[error] EitherStrNum(42) >>> Right[42]
ã³ã³ãã¢ã確èªããŸãã
EitherStrNum(1) >> (lambda x: EitherStrNum(x + 1)) >>> Right[2] EitherStrNum(1) >> (lambda x: EitherStrNum("error")) \ >> (lambda x: EitherStrNum(x + 1)) >>> Left[error]
f.either_wraps
ãã³ã¬ãŒã¿ã¯ã颿°ãã¢ããã³ã³ã¹ãã©ã¯ã¿ã«ããŸãã
@f.either_wraps(f.p_str, f.p_num) def ediv(a, b): if b == 0: return "Div by zero: %s / %s" % (a, b) else: return a / b @f.either_wraps(f.p_str, f.p_num) def esqrt(a): if a < 0: return "Negative number: %s" % a else: return math.sqrt(a) EitherStrNum(16) >> (ediv, 4) >> esqrt >>> Right[2.0] EitherStrNum(16) >> (ediv, 0) >> esqrt >>> Left[Div by zero: 16 / 0]
IO
IOã¢ããïŒå
¥åºåïŒã¯ããã¡ã€ã«ã®èªã¿åããããŒããŒãå
¥åãç»é¢ãžã®å°å·ãªã©ãããŒã¿ã®å
¥åºåãåé¢ããŸãã ããšãã°ããŠãŒã¶ãŒåãèŠæ±ããå¿
èŠããããŸãã ã¢ããããªããã°ã raw_input
ã§ãããããã¯æœè±¡åãæžãããå¯äœçšã§ã³ãŒããè©°ãŸãããŸãã
ããŒããŒãå
¥åãåé¢ããæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
IoPrompt = f.io(lambda prompt: raw_input(prompt)) IoPrompt("Your name: ")
ã¢ãããååŸããã®ã§ããããããã«çµç«ã©ã€ã³ã«è»¢éã§ããŸãã æ¬¡ã®äŸã§ã¯ãååãå
¥åããŠè¡šç€ºããŸãã f.io_wraps
ãã³ã¬ãŒã¿ã¯ã颿°ãã¢ããã³ã³ã¹ãã©ã¯ã¿ãŒã«å€æããŸãã
import sys @f.io_wraps def input(msg): return raw_input(msg) @f.io_wraps def write(text, chan): chan.write(text) input("name: ") >> (write, sys.stdout) >>> name: Ivan
ãšã©ãŒ
ãšã©ãŒã¢ãããTryïŒãšã©ãŒã詊è¡ïŒãå®çšçãªèгç¹ããéåžžã«äŸ¿å©ã§ãã äŸå€ãåé¢ããèšç®ã®çµæãå
éšã«æ£ããå€ãæã€Success
ã€ã³ã¹ã¿ã³ã¹ããŸãã¯Failture
ããäŸå€ãæã€Failture
ã§ããããšã確èªããŸãã
Maybe andeitherãšåæ§ã«ãã¢ãããã€ãã©ã€ã³ã¯è¯å®çãªçµæã®ããã«ã®ã¿å®è¡ãããŸãã
, . Success
, Failture
:
Error = f.error(lambda a, b: a / b) Error(4, 2) >>> Success[2] Error(4, 0) >>> Failture[integer division or modulo by zero]
.get
Failture
. ? .recover
:
Error(4, 0).get() ZeroDivisionError: integer division or modulo by zero
( ), . Success
. . , Success
. :
def handler(e): logger.exception(e) return 0 Error(4, 0).recover((ZeroDivisionError, TypeError), handler) >>> Success[0]
. :
@f.error_wraps def tdiv(a, b): return a / b @f.error_wraps def tsqrt(a): return math.sqrt(a) tdiv(16, 4) >> tsqrt >>> Success[2.0] tsqrt(16).bind(tdiv, 2) >>> Success[2.0]
, . , , ? ?
do-, . :
def mfunc1(a): return f.Just(a) def mfunc2(a): return f.Just(a + 1) def mfunc3(a, b): return f.Just(a + b) mfunc1(1) >> (lambda x: mfunc2(x) >> (lambda y: mfunc3(x, y)))
, mfunc3
, . x
y
. .
ãããã«
, f
. , . , . â .
. â . Pypi .
, .
. ãæž
èŽããããšãããããŸããã