Java 8ã颿°åã£ã½ã使ãããã®ãã¾ããªããF#ã§ãã£ã¦ã¿ã
Java 8を関数型っぽく使うためのおまじない - きしだのはてな
Java 8を関数型っぽく使うためのおまじないをC#でやってみた - ぐるぐる~
Java ã C# ã大å¤ã§ããã F# ããã¯ãã©ã ãå¼ã颿°åãæåãã使ããã®ã§ãä¼¼ããããªãã¨ã¯ãã§ã«ã§ãã¾ãã ä¸è¨ã®è¨äºã®ãã¯ãªãªã®ã§ãä¸è¨ã®è¨äºãã¾ãã¯èªãã§ããèªããã¨ããããããã¾ãã
颿°å(颿°ã表ãåã®æ¹)
F# ã§ã¯ FSharpFunc ã¨ããåãããã¾ããåå空éãåãã©ã¡ã¼ã¿ã¾ã§å«ããã¨ãMicrosoft.FSharp.Core.FSharpFunc<'T, 'U>
ã§ãã
ãã ããã®åãç´æ¥ä½¿ããã¨ã¯ããã¾ããããè¦ããã¨ããããããªãã§ãã
ãã®ä»£ããã«ã'T -> 'U
ã¨ãã表è¨ã使ãã¾ããã'T
ãåãåã£ã¦ 'U
ãè¿ã颿°ãã¨èªã¿ã¾ãã
ã¡ãªã¿ã«ãåãã©ã¡ã¼ã¿ã®æåã«ã'ããä»ãã¦ããã®ãå²ã¨å¤§äºãªãã¨ãªã®ã§ããã
ããã¯ã¾ãæ©ä¼ãããã°ã¨ãããã¨ã§ä»åã¯ãåãã©ã¡ã¼ã¿ã®ä¸æåç®ã¯ã'ããå¿
è¦ããããã«æã£ã¦ããã¦ãã ããã
ãããªæãã§ä½¿ãã¾ãã
(* F#ã§ã¯//å½¢å¼ã®ä¸è¡ã³ã¡ã³ãã使ãããã©ã ã¯ã¦ãªããã°ãF#ã®ã·ã³ã¿ãã¯ã¹ãã¤ã©ã¤ãã«å¯¾å¿ãã¦ãªãã®ã§ã ãã®è¨äºã§ã¯ãããã¯ã³ã¡ã³ãã使ãã¾ã(OCamlã®ã·ã³ã¿ãã¯ã¹ãã¤ã©ã¤ãã使ã£ã¦ã¾ã)ã *) (* Java: Function<String, String> enclose = s -> "[" + s + "]"; *) (* C#: Func<string, string> enclose = s => "[" + s + "]"; *) let enclose = fun s -> "[" + s + "]"
åãå ¨ç¶æ¸ãã¦ã¾ãããã夿°ã«åãæè¨ããã¨ããããªãã¾ãã
let enclose: string -> string = fun s -> "[" + s + "]"
ãããå¼ã³åºããã¨ããã¨ããããªæãã«ãªãã¾ãã
(* 弿°ã()ã§å²ãå¿ è¦ã¯ãªã *) System.Console.WriteLine(enclose "foo") (* System.Console.WriteLineã®å¼æ°ãã«ãã³ã§å²ã£ã¦ããããã«æãããã©ã ã©ã¡ããã¨ããã¨enclose "foo"å ¨ä½ãã«ãã³ã§å²ã£ã¦ããæã *)
ããããã¨ã次ã®ãããªè¡¨ç¤ºã«ãªãã¾ãã
[foo]
ããã²ã¨ã¤é¢æ°ãå®ç¾©ãã¦ã¿ã¾ããããæåã®æåã大æåã«ãã颿°ã§ãã
(* sã®åãæç¤ºããªãã¨ãã¡ã½ããå¼åºããåºæ¥ãªãã®ã§æç¤ºãã¦ãã *) let capitalize = fun (s: string) -> s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower()
2æåæªæºã®æååãä¸ããã¨æ»ã«ã¾ãã
å¼ã³åºãã¦ã¿ã¾ãã
System.Console.WriteLine(capitalize "foo") (* => Foo *)
ãã®2ã¤ãé ã«å¼ã³åºãã¦ãcapitalize ã㦠enclose ãããã¨ããã¨ããããªæãã«ãªãã¾ããã
System.Console.WriteLine(enclose (capitalize "foo")) (* => [Foo] *)
ããããå ´åãJava ã§ã¯ andThen ã使ã£ã¦é£çµããC# ã§ã¯æ¡å¼µã¡ã½ãããå®ç¾©ãã¾ãããã
F# ã§ã¯ >>
ã¨ãã颿°ãç¨æããã¦ãã¾ãã
使ã£ã¦ã¿ã¾ãããã
System.Console.WriteLine((capitalize >> enclose) "foo");
ããã¯ã颿°åæã§ããã
let capEnc = capitalize >> enclose System.Console.WriteLine(capEnc "foo")
F# ã¯é¢æ°åã£ã½ããã¨ãç°¡åã«ã§ãã¾ããã¹ããï¼
颿°
ã¨ããã§ãF# ã§ã¯ let f = fun x -> ...
㯠let f x = ...
ã¨æ¸ããã¨ãåºæ¥ã¾ãã
ããã使ãã¨ãä»ã¾ã§ã®ã³ã¼ãã¯ããæ¸ãã¾ãã
let enclose s = "[" + s + "]" let capitalize (s: string) = s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower() let capEnc = capitalize >> enclose System.Console.WriteLine(capEnc "foo")
ããã¦ããã® let f x = ...
ã¯é¢æ°å®ç¾©ã§ãã
颿°å㯠'T -> 'U
ã§ããããä¸ã§å®ç¾©ãã enclose 颿°ã®ã·ã°ããã£ããstring -> string
ã®ããã«è¡¨ãã¾ãã
ã©ã ãå¼ã¨é¢æ°ãã·ã¼ã ã¬ã¹ã«ã¤ãªãã£ã¦ãã¦ãã¨ã¦ãè¯ãæãã§ãã
å¥åã使ã?
'T -> 'U
ããã§ã« Microsoft.FSharp.Core.FSharpFunc<'T, 'U>
ã®å¥åã®ãããªãã®ãªã®ã§ãå¿
è¦ãªãã§ããã
ããã«ã忍è«ãå¹ãã®ã§åãæ¸ãå¿
è¦ã¯ã»ã¨ãã©ã®å ´åã§ããã¾ããã
unit
Java ã§ã C# ã§ããæ»ãå¤ãè¿ããªã颿°ã¯ Function/Func ã¨ã¯å¥ã®ãã®ãå¿
è¦ã§ããã
ããã¯ãvoid ã¨ããã®ãç¹æ®ãªãã®ãªã®ãåå ã§ãã
ããããF# ã§ void ã«ç¸å½ãã unit ã¯ãä»ã®ååæ§å¤ãæã¤(ã()ãã¨ããå¯ä¸ã®å¤ãæã¤)ã®ã§ãç¹å¥æ±ãã¯ä¸è¦ã§ãã
ä½ã®åé¡ããªããstring -> unit
ã使ãã¾ãã
(* let writeLine (str: string) = System.Console.WriteLine(str) ã¨ãã§ãå¯ *) let writeLine: string -> unit = System.Console.WriteLine let enclose s = "[" + s + "]" writeLine (enclose "foo") let capitalize (s: string) = s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower() writeLine (capitalize "foo")
ããã¾ã§ã§ã1弿°ã®é¢æ°åãã使ã£ã¦ãã¾ãããã2弿°ä»¥ä¸ã®é¢æ°ã¯çããªã®ã§ã1弿°ã®é¢æ°ãå®ç¾©ã§ããã°åé¡ããã¾ããã
ã㨠F# ã®é¢æ°ã§ãã FSharpFunc<'T, 'U>
ã«ã¯ BiFunction
ãã Func<TArg1, TArg2, TResult>
ãªãã¦ãã®ã¯ããã¾ãããä½ã®åé¡ãããã¾ããã
颿°åæ
颿°åæã¯æ¬¡ã®ããã«æ¸ãã¾ãã
writeLine ((capitalize >> enclose) "foo")
writeLine ãç¹å¥æ±ãããªãã¦ããã®ã§ãããã«åæã§ãã¾ããã
(capitalize >> enclose >> writeLine) "foo"
ããã«ããã²ã¨ã¤é¢æ°ãç¨æãã¦ã次ã®ããã«æ¸ãã¦ã¿ã¾ããçãä¸ããããåãåºã颿°ã§ãã
let middle = (fun s: string) -> s.Substring(s.Length / 3, s.Length - s.Length * 2 / 3) (middle >> capitalize >> enclose >> writeLine) "yoofoobar"
颿°åæã使ããªãã¨ã次ã®ããã«ãªãã¾ããã
writeLine (enclose (capitalize (middle "foobaryah")))
ãã®ããã«ãå®éã«å¼ã³åºãé ã¨è¨è¿°ãéã«ãªãã¾ããmiddle ã㦠capitalize ã㦠enclose ã㦠writeLine ããã®ã«ãå ã« writeLine ããæ¸ãå¿ è¦ãããã¾ãã ã¾ããã«ãã³ããã¾ã£ã¦ããã®ã§ãæå¾ã«ã¾ã¨ãã¦ã«ãã³ãéããå¿ è¦ãããã¾ããã¡ãã£ã¨é¢æ°å¼ã³åºããå¢ããã¨ãéãã«ãã³ã®æ°ãåãããªããªã£ã¦ã³ã³ãã¤ã«ã¨ã©ã¼ããªããªãã¨ããã¾ã§ã)ããå¢ããããæ¸ãããããªãã¦ãã¨ãããã¾ãããï¼
F# ã§ã¯ããã«ããã¤ãã©ã¤ã³æ¼ç®åã¨ãããã®ãããã®ã§ãããæ¸ããã¨ãã§ãã¾ãã
"yoofoobar" |> middle |> capitalize |> enclose |> writeLine
ã"yoofoobar"ãmiddleãã¦capitalizeãã¦encloseãã¦writeLineããããã¨ãã³ã¼ãã§èªç¶ã«è¡¨ãã¦ãã¾ããã ãããæ¹è¡ããã¨ã»ã»ã»
"yoofoobar" |> middle |> capitalize |> enclose |> writeLine
ããã
ã«ãªã¼åå½¢å¼
ãã¦ã2弿°ä»¥ä¸ã®é¢æ°ã¯çãã¨æ¸ãã¾ããããå®é2ã¤ä»¥ä¸ã®ãã©ã¡ã¼ã¿ã渡ãããã¨ãã¯ã©ãããã°ãããã§ãããï¼ ããããã¨ãã«ä½¿ãã®ãã«ãªã¼åã§ããã«ãªã¼åã¯ãã²ã¨ã¤ã®å¼æ°ãåã£ã¦é¢æ°ãè¿ããã¨ã§ãè¤æ°ã®ãã©ã¡ã¼ã¿ã«å¯¾å¿ãã¾ãã
ä¾ãã°ãã¯ããæååã¨ã¯ãã¾ããæååãæå®ãã¦ãæååãã¯ãã颿°ã¯ãC# ã®2弿°é¢æ°ã§ãããããªããããªãã§ãããã
string Sandwich(string tag, string str) { return tag + str + tag; }
ãããã«ãªã¼åå½¢å¼ã®é¢æ°ã§æ¸ãã¨ã次ã®ããã«ãªãã¾ãã
(* ä¸é¨åæå®ããã¦ã¾ãããæ°ã«ãããè² ãã§ã *) let sandwich (tag: string) = fun str -> tag + str + tag
sandwich èªä½ã¯ããæååãåã£ã¦ããæååãåã£ã¦æååãè¿ã颿°ããè¿ã颿°ãã«ãªã£ã¦ãã¾ãã
å¼ã³åºãã¯æ¬¡ã®ããã«ãªãã¾ãã
writeLine (sandwich "***" "sanded!") (* => ***sanded!*** *)
3弿°ã ã¨ãããªæãã§ããã
let encloseC (openStr: string) = fun closeStr -> fun str -> openStr + str + closeStr
encloseC ã¯ããæååãåã£ã¦ããæååãåã£ã¦ããæååãåã£ã¦æååãè¿ã颿°ããè¿ã颿°ããè¿ã颿°ãã«ãªã£ã¦ãã¾ãã
å¼ã³åºãã¯ãããªæãã§ã
writeLine (encloseC "{" "}" "enclosed!") (* => {enclosed!} *)
ã¨ããã§ããã®ã«ãªã¼åå½¢å¼ã® encloseCã弿°ãé¨åçã«æ¸¡ãã¦ãããã¨ãåºæ¥ã¾ãã
let encloseCurly = encloseC "{" "}" writeLine (encloseCurly "å²ã¾ããï¼")
ãããã£ã¦é¨åé©ç¨ãããã¨ã§ãæ°ãã颿°ãä½ããããã§ãã ã¡ãªã¿ã« Curly ã¯ãæ³¢ã«ãã³=ã«ã¼ãªã¼ãã©ã±ããã{ï½}ãã®ãã¨ã§ãã«ãªã¼åã¨ã¯é¢ä¿ãªãã®ã§ãããããã
ã¨ããã§ã¨ããã§ãF# ã§ã¯ãã¹ããã fun ãã¾ã¨ãããã¨ãã§ãã¾ãã ä¾ãã°ãencloseC ã¯ãããªå®ç¾©ã§ããã
let encloseC (openStr: string) = fun closeStr -> fun str -> openStr + str + closeStr
2ã¤ã fun ãããã¾ãããã¾ã¨ãã¦ãã¾ãã¾ãããã
let encloseC (openStr: string) = fun closeStr str -> openStr + str + closeStr
ã¹ãããªãã¾ãããï¼
ã¨ããã§ã¨ããã§ã¨ããã§ãF# ã§ã¯ let f = fun x -> ...
㯠let f x = fun x -> ...
ã¨æ¸ããã®ã§ããã
fun ãã¾ã¨ããåã®å®ç¾©ã«æ»ãã¨ã
let encloseC (openStr: string) = fun closeStr -> fun str -> openStr + str + closeStr
ã§ããã®ã§ããfãã®é¨åããencloseC (openStr: string)ãã ã¨æã£ã¦ã¿ãã¨ã»ã»ã»
let encloseC (openStr: string) closeStr = fun str -> openStr + str + closeStr
ã¨ãªã£ã¦ãããã«
let encloseC (openStr: string) closeStr str = openStr + str + closeStr
ããã§ããï¼
ã¾ã¨ã
Action 以éã®ã½ã¼ã¹ããããªæãã§ãã
let writeLine (str: string) = System.Console.WriteLine(str) let enclose s = "[" + s + "]" writeLine (enclose "foo") let capitalize (s: string) = s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower() writeLine (capitalize "foo") (* 颿°åæ *) (capitalize >> enclose >> writeLine) "foo" let middle (s: string) = s.Substring(s.Length / 3, s.Length - s.Length * 2 / 3) (middle >> capitalize >> enclose >> writeLine) "yoofoobar" writeLine (enclose (capitalize (middle "foobaryah"))) (* ã«ãªã¼åå½¢å¼ *) let sandwich (tag: string) str = tag + str + tag writeLine (sandwich "***" "sanded!") let encloseC (openStr: string) closeStr str = openStr + str + closeStr writeLine (encloseC "{" "}" "enclosed!") (* é¨åé©ç¨ *) let encloseCurly = encloseC "{" "}" writeLine (encloseCurly "å²ã¾ãã!")
ãã¾ã
Java ã C# ã§ã¯ãã©ã ãå¼ã¨é常ã®ã¡ã½ããã®éã«ã¯å¤§ããªå·®ãããã¾ããã ãã®ä¸ä¾ã¨ãã¦ãã¸ã§ããªãã¯ãªé¢æ°ãå®ç¾©ã§ããªããã¨ãããã®ãããã¾ããã ããããF# ã§ã¯ã©ã ãå¼ã¨é常ã®é¢æ°ã¯ã·ã¼ã ã¬ã¹ã«ã¤ãªãã£ã¦ãã¾ãã ãã®ããã
(* 颿° *) let id x = x
ã¯ãã¡ããã§ãããã
(* ã©ã ãå¼ *) let id = fun x -> x
ãã§ãã¾ãã 表è¨ä¸ã§ããæ®éã®é¢æ°ã¨ã©ã ãå¼ãç¨ããå®ç¾©ã¯ Java ã C# ã»ã©ã®å·®ã¯ããã¾ããã