Arrowã«ããHaskellããã°ã©ãã³ã°ã®åºç¤ãâ¦ãã¤ãæè¦ã§é 次/åå²/ç¹°è¿ã
Programming with Arrowsãèªãã§çè§£ããã¤ããã®ã¡ã¢ã誤ããªã©ä¹ããææã
ï¼å¾©ç¿ï¼Arrowã£ã¦ãªã«ï¼
ã¨æã£ã¦ä»¥å調ã¹ãã¡ã¢ã"3分で解るHaskellのArrowの基本メモ - よくわかりません"ãããã«ã¡ãã£ã¨è£è¶³ã¨ããã観ç¹ãå¤ãã¦ã¾ãæè¦ã®æ´çã
Monadã«è²ããªç¨®é¡ãããããã«ãArrowãè²ããªç¨®é¡ãããã
ãã種é¡ã®Monadã«è²ããªåã®è²ããªå¤ãå
¥ããããããã«ããã種é¡ã®Arrowã«è²ããªåã®è²ããªé¢æ°ãå
¥ããããã
- Monad: Maybeã®ä¾â ãMaybe Intã ã«return 0ãreturn 777ãOKããMaybe Charã ã«return 'a'ãreturn ' 'ãOKã
- Arrow: (->)ã®ä¾â ãInt -> Intã ã«arr (+1) ãarr (*2)ãOKããChar -> Charã ã«arr toUpperãarr toLowerãOKã
æ®éã«ãã¤ãã§ç¹ã â¦ é æ¬¡å¦çæ§é
ãµã¤ãã«Arrowãã>>>ãã§ç¹ããArrowã®ç¨®é¡ã(->)ã¤ã¾ã颿°ãã®ã¾ãã¾ã®å ´åã®ä¾ã ã¨ã
numOddOver10 :: (->) [Int] Int numOddOver10 = (filter odd) >>> (filter (>10)) >>> length
ã®ããã«ï¼ã¤ã®Arrowï¼ã®ã¤ã³ã¹ã¿ã³ã¹ã§ãã(->)ï¼
- (filter odd) :: (->) [Int] [Int]
- (filter (>10)) :: (->) [Int] [Int]
- length :: (->) [Int] Int
ãã>>>ã§ç¹ãã§å ¨ä½ã§(->) [Int] IntãªArrowï¼ã®ã¤ã³ã¹ã¿ã³ã¹ã§ãã(->)ï¼ãä½ãããã¾ãã«Unixã®ã·ã§ã«ã§ã³ãã³ãããã¤ã(|)ã§ç¹ãæè¦ã
使ã£ã¦ã¿ãã¨ãããªæãã
Main> numOddOver10 [0,1,10,8,13] 1 Main>
çµæããä»ã®å¦çã®ãã¨ã§ä½¿ã â¦ å¤æ°ã®ä»£æ¿
Unixã®ã·ã§ã«ã§ã³ãã³ãããã¤ã(|)ã§ç¹ãã¦ã¦å°ãã®ããåºåãæ¬¡ã®ã³ãã³ããããªãã¦ãã£ã¨å¾ã®ã³ãã³ãã«æ¸¡ãããå ´åããã®å ´åã䏿ãã¡ã¤ã«ã®ãããªå¤é¨è¨æ¶ã«ä¸åº¦åãã¦ã¾ãèªãã¨ããäºã«ãªããã©ãArrowã§ã¯æµããè«çä¸ä¸¦å*1ã«ã§ããã
ããã«ä¾¿å©ãªã®ãArrowã®ã¯ã©ã¹ã¡ã½ãã(&&&)ã
(&&&) :: arrow a b -> arrow a b' -> arrow a (b,b')
wikibooksにある概念図ãã¿ãã¨ã©ããªãã®ãè§£ããããã
使ç¨ä¾ãå ã®ä¾ã®æ¹å¤ã§ããã ã®å¥æ°ã¯1ãã¤ã³ãã10ãã大ãã奿°ã¯ããã«10ãã¤ã³ãã¨ãã¦ã«ã¦ã³ãããã
numOddOver10Weighted :: (->) [Int] Int numOddOver10Weighted = filter odd >>> ((filter(>10)>>>length>>>(*10)) &&& length) >>> uncurry (+)
filter oddã®åºåãäºè¡ã«åããã¦ã䏿¹ã¯&&&ã®å·¦(filter(>10)>>>length>>>(*10))ãéãã䏿¹ã¯&&&ã®å³(length)ãéãããããã®åºåãã¿ãã«ã«ã¾ã¨ãããã¦ã¾ãï¼æ¬ã«ãªã£ã¦uncurry (+)ã«æµããã
ã¾ãã«ãã¤ãæè¦ã¨ãããæµãã¦ãæè¦ã
並åç³»ã¯ã©ã¹ã¡ã½ããã¯ãã»ãã«firstãsecondã(***)ããããããããã©ããªãããã¯wikibooksã®å³ãè¦ãã°è§£ãã
ãã ãæµããè¤éã«ãªã£ããdo記法のArrow用拡張版ã§ç´ ç´ã«å¤æ°ã使ã£ãæ¹ãè§£ããããããã
å¤ã«ãã£ã¦å¦çãåãã ⦠æ¡ä»¶å岿§é
Unixã®ã·ã§ã«ã§ã®ãã³ãã³ãã®ãã¤ãé£çµã ã¨ãæä¸ã*2ãã·ã§ã«ã¹ã¯ãªããã§ifæã®åºçªã
Arrowã®å ´åããArrowä¸è¬ã ã¨ãæä¸ãã ãã©ãArrowChoiceã¨ãããµãã¯ã©ã¹ã®ç¯å²ã§ã¯å¤§ä¸å¤«ãArrowã®æ å ã§æ¡ä»¶åå²ãåºæ¥ãã(->)ãKleisli mããArrowChoiceã®ã¤ã³ã¹ã¿ã³ã¹ã«ãªã£ã¦ããã大ä¸å¤«ã
ArrowChoiceã®ã¯ã©ã¹ã¡ã½ãããããããµãã¤ã®Arrowãæ¸¡ãã¦ãæ¡ä»¶ã«ãã£ã¦ãã®ã©ã£ã¡ãã ããéãArrowãä½ã£ã¦ãããã
(|||) :: arrow a c -> arrow b c -> arrow (Either a b) c
æ¡ä»¶å ¥åã«ã¯Boolã®ä»£ããã«Eitherã使ããã¤ã¡ã¼ã¸ã¯ä¸ã«æ¸ãã&&&ã«è¿ããArrowãµãã¤( arrow a c 㨠arrow b c )ãåããarrow (Either a b) cã«åæãããåæãããArrowã¯ãå ¥åãLeft aãªã arrow a cã«æµããarrow b cã¯ä½¿ãããªããå ¥åãRight bãªããã®éã
使ç¨ä¾ã20ãã大ããè¦ç´ ãããå ´åã¯å¥æ°ã§ããè¦ç´ æ°ããªãå ´åã¯10ãã大ããè¦ç´ æ°ãã«ã¦ã³ãããã
numOddOrOver10 :: (->) [Int] Int numOddOrOver10 = hasOver20 >>> (filter(>10) ||| filter odd) >>> length where hasOver20 ns | any (>20) ns = Right ns | otherwise = Left ns
Rightã®æã¯|||ã®å³ã®ArrowãéããLeftã®æã¯|||ã®å·¦ã®Arrowãéãã
ArrowChoiceã®ã¯ã©ã¹ã¡ã½ããã¯ãã»ãã«leftãrightã(+++)ããããããããã©ããªãããã¯リファレンスã¨ãåç
§ã
ä¸å®æ¡ä»¶ã®éã¯ç¹°ãè¿ã ⦠繰ãè¿ãæ§é
forã¨ãwhileã§ãããã¯ããã¤ãã§ã¯æãå¾ã¾ããããArrowã§ã¯æå¾ã«èªåãæã£ã¦ããã°ãkã
ra = ga>>>fa>>>ra
ãã¡ããããããç¡éã«ã¼ããªã®ã§ã
ra = ga>>>fa'>>>(ra|||arr id)
ã¿ããã«æ¡ä»¶åå²ã¨çµã¿åãããã
ï¼è¿½è¨:å½åãããã«ArrowApplyでループã¨ããè¨äºãæ¸ãããã¦ããã©ãèªåã®ã¬ã»å¦æ³ã ã£ãããã§ãããã¿ã¾ããï¼
ã¨ããããã§ä½ã§ãåºæ¥ã
ä¸è¨ã®éãã夿°ã®ä»£æ¿ããã£ã¦ã順次処理構造、条件分岐構造、繰り返し構造ãä½ããã®ã§ãã©ããªããã°ã©ã ã§ãæ¸ããã¯ãã
ããããããã+ ããããã+ãã+ããããã ï¼ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ï¿£ ãããã â§ï¼¿â§ããããï¼ã ãã¼ãæ§é åå®çã®ï¼æ§é ã ã¼ï¼ãï¼æ§é ã ã¼ ãã brï¼Â´âï½ãï¼ï¾ï½°ï½² !ã |ã ããä½ã§ãã§ãããã¼ ã+ ããã½ ãããã¤ã ãã \______________ ããã ãã(â_ã ããã ãã ã'ãã;;::â::
ãããã¦ãç´ç²é¢æ°åè¨èªHaskellã®ä¸ã«æç¶ãããã°ã©ãã³ã°ãè¯éºã«åçºæï¼
注æãå®éã¯ã¡ããã¨arrãã¦Arrowã«
ããã¾ã§æ¸ããä¾ã¯(->)以å¤ã®Arrowã§ã¯ä½¿ããªãã³ã¼ãã(->)以å¤ã®Arrowã§ã使ããã³ã¼ãã«ããã«ã¯ãä¸ã®ããã«é¢æ°ãarrãã¦Arrowã«ãã¦ãããªãã¨ã ãã
numOddOver10 :: Arrow arrow => arrow [Int] Int numOddOver10 = arr (filter odd) >>> arr (filter (>10)) >>> arr length
numOddOver10Weighted :: Arrow arrow => arrow [Int] Int numOddOver10Weighted = arr (filter odd) >>> ((arr (filter(>10))>>>arr length>>>arr (*10)) &&& arr length) >>> arr (uncurry (+)) --ãã£ã¡ã§ã --numOddOver10Weighted' = arr (filter odd) >>> (arr ((10*).length.(filter(>10))) &&& arr length) >>> arr (uncurry (+)) --numOddOver10Weighted'' = arr (filter odd) >>> (arr ((filter(>10))>>>length>>>(*10)) &&& arr length) >>> arr (uncurry (+))
numOddOrOver10 :: ArrowChoice arrow => arrow [Int] Int numOddOrOver10 = arr hasOver20 >>> (arr (filter(>10)) ||| arr (filter odd)) >>> arr length where hasOver20 ns | any (>20) ns = Right ns | otherwise = Left ns
æããªããã¨ã§æ¸ãç´ãããâ¦ã
追è¨:æ®éã®Arrowã§ã¯ç¹°ãè¿ãæ§é ãåºæ¥ãªãã¿ããã«æ¸ãã¦ãã®ãä¿®æ£ã
*1:å®è¡ãåæã¨ããããã§ã¯ãªã
*2:ãã¡ããã³ãã³ãèªä½ãæ¡ä»¶ã«ãã£ã¦å¦çãå¤ããã®ã¯å¯è½ãããã¯Arrowã§ãArrowã®ä¸ã®é¢æ°ãæ¡ä»¶ã«ãã£ã¦å¦çãå¤ããã®ã¨åããããã§ã¯Arrowã®ã¬ãã«ã§ã®æ¡ä»¶åå²ã®ã«ã¼ã«ï¼ãã¼ã«ï¼ã®è©±