Note
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãµã€ã³ã€ã³ãŸãã¯ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããã¥ã¡ã³ãã¯ãF# ã³ã³ããŒãã³ãèšèšã¬ã€ãã©ã€ã³ãv14ãMicrosoft Researchãããã³ F# Software Foundation ã«ãã£ãŠæåã«ãã¥ã¬ãŒã·ã§ã³ããã³ç®¡çãããããŒãžã§ã³ã«åºã¥ããF# ããã°ã©ãã³ã°ã®ã³ã³ããŒãã³ãèšèšã¬ã€ãã©ã€ã³ã®ã»ããã§ãã
ãã®ããã¥ã¡ã³ãã§ã¯ãF# ããã°ã©ãã³ã°ã«ã€ããŠçè§£ããŠããããšãåæãšããŠããŸãã ãã®ã¬ã€ãã®ããŸããŸãªããŒãžã§ã³ã«å¯Ÿãã F# ã³ãã¥ããã£ã®è²¢ç®ãšåœ¹ã«ç«ã€ãã£ãŒãããã¯ã«æè¬ããŸãã
æŠèŠ
ãã®ããã¥ã¡ã³ãã§ã¯ãF# ã³ã³ããŒãã³ãã®èšèšãšã³ãŒãã£ã³ã°ã«é¢é£ããããã€ãã®åé¡ã«ã€ããŠèª¬æããŸãã ã³ã³ããŒãã³ãã¯ã次ã®ãããããæå³ããå ŽåããããŸãã
- ãã®ãããžã§ã¯ãå ã«å€éšã³ã³ã·ã¥ãŒããŒãå«ãŸãã F# ãããžã§ã¯ãå ã®ã¬ã€ã€ãŒã
- ã¢ã»ã³ããªå¢çãè¶ã㊠F# ã³ãŒãã§äœ¿çšããããšãç®çãšããã©ã€ãã©ãªã
- ã¢ã»ã³ããªå¢çãè¶ããŠä»»æã® .NET èšèªã§äœ¿çšããããšãç®çãšããã©ã€ãã©ãªã
- NuGetãªã©ãããã±ãŒãž ãªããžããªçµç±ã§ã®é åžãç®çãšããã©ã€ãã©ãªã
ãã®èšäºã§èª¬æããææ³ã¯ãåªãã F# ã³ãŒãã® 5 ã€ã®ååã«åŸããå¿ èŠã«å¿ããŠé¢æ°åããã°ã©ãã³ã°ãšãªããžã§ã¯ã ããã°ã©ãã³ã°ã®äž¡æ¹ãå©çšããŸãã
ææ³ã«é¢ä¿ãªããã³ã³ããŒãã³ãããã³ã©ã€ãã©ãª ãã¶ã€ããŒã¯ãéçºè ãæãç°¡åã«äœ¿çšã§ãã API ãäœæããããšãããšãã«ãå®çšçã§å®çšçãªåé¡ã«çŽé¢ããŸãã .NET ã©ã€ãã©ãªèšèšã¬ã€ãã©ã€ã³ ã®è¯å¿çãªã¢ããªã±ãŒã·ã§ã³ã¯ã䜿çšããã®ã楜ããäžè²«æ§ã®ãã API ã®ã»ããã®äœæã«åããŠå°ããŸãã
äžè¬çãªã¬ã€ãã©ã€ã³
ã©ã€ãã©ãªã®å¯Ÿè±¡ãŠãŒã¶ãŒã«é¢ä¿ãªããF# ã©ã€ãã©ãªã«é©çšããããŠãããŒãµã« ã¬ã€ãã©ã€ã³ãããã€ããããŸãã
.NET ã©ã€ãã©ãªã®èšèšã¬ã€ãã©ã€ã³ã«ã€ããŠèª¬æããŸã
ããªããè¡ã£ãŠããF#ã³ãŒãã£ã³ã°ã®çš®é¡ã«é¢ä¿ãªãã.NETã©ã€ãã©ãªãã¶ã€ã³ã¬ã€ãã©ã€ã³ã«é¢ããå®çšçãªç¥èãæã€ããšã¯äŸ¡å€ããããŸãã ä»ã®ã»ãšãã©ã® F# ããã³ .NET ããã°ã©ãã¯ããããã®ã¬ã€ãã©ã€ã³ã«ç²ŸéããŠããã.NET ã³ãŒãããããã«æºæ ããããšãæåŸ ããŠããŸãã
.NET ã©ã€ãã©ãªã®èšèšã¬ã€ãã©ã€ã³ã§ã¯ãååä»ããã¯ã©ã¹ãšã€ã³ã¿ãŒãã§ã€ã¹ã®èšèšãã¡ã³ããŒã®èšèš (ããããã£ãã¡ãœãããã€ãã³ããªã©) ãªã©ã«é¢ããäžè¬çãªã¬ã€ãã³ã¹ãæäŸãããããŸããŸãªèšèšã¬ã€ãã³ã¹ã®åèãšããŠåœ¹ç«ã¡ãŸãã
XML ããã¥ã¡ã³ãã³ã¡ã³ããã³ãŒãã«è¿œå ãã
ãããªã㯠API ã«é¢ãã XML ããã¥ã¡ã³ãã䜿çšãããšããããã®åãšã¡ã³ããŒã䜿çšãããšãã«ãŠãŒã¶ãŒãåªãã Intellisense ãš Quickinfo ãååŸããã©ã€ãã©ãªã®ããã¥ã¡ã³ã ãã¡ã€ã«ãäœæã§ããããã«ãªããŸãã xmldoc ã³ã¡ã³ãå ã®è¿œå ããŒã¯ã¢ããã«äœ¿çšã§ããããŸããŸãª xml ã¿ã°ã«ã€ããŠã¯ãXML ããã¥ã¡ã³ãã® ãåç §ããŠãã ããã
/// A class for representing (x,y) coordinates
type Point =
/// Computes the distance between this point and another
member DistanceTo: otherPoint:Point -> float
çã圢åŒã® XML ã³ã¡ã³ã (/// comment) ãŸãã¯æšæº XML ã³ã¡ã³ã (///<summary>comment</summary>) ã䜿çšã§ããŸãã
å®å®ããã©ã€ãã©ãªãšã³ã³ããŒãã³ã API ã«æç€ºçãªçœ²åãã¡ã€ã« (.fsi) ã䜿çšããããšãæ€èšããŠãã ãã
F# ã©ã€ãã©ãªã§æç€ºçãªçœ²åãã¡ã€ã«ã䜿çšãããšããããªã㯠API ã®ç°¡æœãªæŠèŠãæäŸãããŸããããã«ãããã©ã€ãã©ãªã®å®å šãªãããªã㯠ãµãŒãã§ã¹ã確å®ã«ææ¡ãããããªã㯠ããã¥ã¡ã³ããšå éšå®è£ ã®è©³çްãæç¢ºã«åé¢ã§ããŸãã 眲åãã¡ã€ã«ã¯ãå®è£ ãã¡ã€ã«ãšçœ²åãã¡ã€ã«ã®äž¡æ¹ã§å€æŽãè¡ãå¿ èŠãããããããªã㯠API ã®å€æŽã«æ©æŠãå ããŸãã ãã®çµæã眲åãã¡ã€ã«ã¯éåžžãAPI ãåºãŸããå€§å¹ ãªå€æŽãäºæ³ãããªããªã£ãå Žåã«ã®ã¿å°å ¥ããå¿ èŠããããŸãã
.NET ã§æååã䜿çšããããã®ãã¹ã ãã©ã¯ãã£ã¹ã«åŸã
ãããžã§ã¯ãã®ç¯å²ããããä¿èšŒããå Žåã¯ã.NET ã®æååã䜿çšããããã®ãã¹ã ãã©ã¯ãã£ã¹ ã«åŸã£ãŠãã ããã ç¹ã«ãæååã®å€æãšæ¯èŒã«ãããæåçæå³ãæç€ºçã«ç€ºãããŠããŸã (該åœããå Žå)ã
F# ã«æ¥ç¶ããã©ã€ãã©ãªã®ã¬ã€ãã©ã€ã³
ãã®ã»ã¯ã·ã§ã³ã§ã¯ããããªã㯠F# ã«æ¥ç¶ããã©ã€ãã©ãªãéçºããããã®æšå¥šäºé ã«ã€ããŠèª¬æããŸããã€ãŸããF# éçºè ã䜿çšããããšãç®çãšãããããªã㯠API ãå ¬éããã©ã€ãã©ãªã§ãã ç¹ã« F# ã«é©çšã§ããã©ã€ãã©ãªèšèšã«é¢ããããŸããŸãªæšå¥šäºé ããããŸãã å ·äœçãªæšå¥šäºé ããªãå Žåã¯ã.NET ã©ã€ãã©ãªã®èšèšã¬ã€ãã©ã€ã³ããã©ãŒã«ãã㯠ã¬ã€ãã³ã¹ã§ãã
ååä»ãèŠå
.NET ã®ååä»ãèŠåãšå€§æåãšå°æåã®è¡šèšèŠåã䜿çšãã
次ã®è¡šã¯ã.NET ã®ååä»ãèŠåãšå€§æåãšå°æåã®è¡šèšèŠåã«åŸããŸãã F# ã³ã³ã¹ãã©ã¯ããå«ããå°ããªè¿œå æ©èœããããŸãã ãããã®æšå¥šäºé ã¯ç¹ã«ãF#ãã F# ã®å¢çãè¶ ãã API ã察象ãšããŠããã.NET BCL ã®ã€ãã£ãªã ãšå€§éšåã®ã©ã€ãã©ãªã«é©åããŸãã
| æ§æäœ | ã±ãŒã¹ | ããŒã | 䜿çšäŸ | ã¡ã¢ |
|---|---|---|---|---|
| å ·è±¡å | PascalCase | åè©/åœ¢å®¹è© | ListãDoubleãComplex | å ·è±¡åã¯ãæ§é äœãã¯ã©ã¹ãåæåãããªã²ãŒããã¬ã³ãŒããããã³å ±çšäœã§ãã OCaml ã§ã¯ãååã¯åŸæ¥å°æåã§ãããF# ã§ã¯åã« .NET ååä»ãã¹ããŒã ãæ¡çšãããŠããŸãã |
| DLL | PascalCase | Fabrikam.Core.dll | ||
| å ±çšäœã®ã¿ã° | PascalCase | åè© | SomeãAddãSuccess | ãããªã㯠API ã§ã¯ãã¬ãã£ãã¯ã¹ã䜿çšããªãã§ãã ããã å¿ èŠã«å¿ããŠãå éšã§äœ¿çšããå Žåã¯ã"type Teams = TAlpha | TBeta | TDelta" ã®ããã«ãã¬ãã£ãã¯ã¹ãä»ããŠãã ããã |
| åºæ¥äº | PascalCase | åè© | å€å€æŽæžã¿/å€å€æŽäž | |
| äŸå€ | PascalCase | WebException | åå㯠"Exception" ã§çµããå¿ èŠããããŸãã | |
| ãã£ãŒã«ã | PascalCase | åè© | çŸåšã®åå | |
| ã€ã³ã¿ãŒãã§ã€ã¹ã®çš®é¡ | PascalCase | åè©/åœ¢å®¹è© | IDisposable | åå㯠"I" ã§å§ãŸãå¿ èŠããããŸãã |
| æ¹åŒ | PascalCase | åè© | ãã¥ãŒã¹ããªã³ã° | |
| Namespace | PascalCase | Microsoft.FSharp.Core | äžè¬çã« <Organization>.<Technology>[.<Subnamespace>]ã䜿çšããŸããããã¯ãããžãçµç¹ããç¬ç«ããŠããå Žåã¯çµç¹ãåé€ããŸãã |
|
| ãã©ã¡ãŒã¿ãŒ | camelCase | åè© | typeNameãtransformãrange | |
| let å€ (å éš) | camelCase ãŸã㯠PascalCase | åè©/åè© | getValueãmyTable | |
| let å€ (å€éš) | camelCase ãŸã㯠PascalCase | åè©/åè© | List.mapãDates.Today | let ãã€ã³ãå€ã¯ãå€ãã®å ŽåãåŸæ¥ã®æ©èœèšèšãã¿ãŒã³ã«åŸããšãã«å ¬éãããŸãã ãã ããäžè¬ã«ãèå¥åãä»ã® .NET èšèªãã䜿çšã§ããå Žåã¯ãPascalCase ã䜿çšããŸãã |
| è²¡ç£ | PascalCase | åè©/åœ¢å®¹è© | IsEndOfFileãBackColor | ããŒã«åããããã£ã¯ãIsNotEndOfFile ã§ã¯ãªã IsEndOfFile ã®ããã«ãäžè¬çã« Is ãš Can ã䜿çšããè¯å®çã§ããå¿ èŠããããŸãã |
çç¥åœ¢ãé¿ãã
.NET ã®ã¬ã€ãã©ã€ã³ã§ã¯ãçç¥åœ¢ã®äœ¿çšã¯æšå¥šãããŸãã (ããšãã°ã"OnButtonClickã§ã¯ãªã OnBtnClick ã䜿çšãã" ãªã©)ã "éåæ" ã® Async ãªã©ãäžè¬çãªçç¥åœ¢ã¯èš±å®¹ãããŸãã ãã®ã¬ã€ãã©ã€ã³ã¯ã颿°åããã°ã©ãã³ã°ã§ã¯ç¡èŠãããããšããããŸããããšãã°ãList.iter 㯠"iterate" ã®çç¥åœ¢ã䜿çšããŸãã ãã®ãããF# ãã F# ãžã®ããã°ã©ãã³ã°ã§ã¯çç¥åœ¢ã®äœ¿çšã蚱容ãããåŸåããããŸãããäžè¬çã«ã¯ãããªã㯠ã³ã³ããŒãã³ãã®èšèšã§ã¯é¿ããå¿
èŠããããŸãã
ååã®å€§æåãšå°æåã«ããè¡çªãé¿ãã
.NET ã¬ã€ãã©ã€ã³ã«ãããšãäžéšã®ã¯ã©ã€ã¢ã³ãèšèª (Visual Basic ãªã©) ã§ã¯å€§æåãšå°æåãåºå¥ãããªãããã倧æåãšå°æåã®éããããªãå Žåã¯ååã®è¡çªãè§£æ¶ã§ããŸããã
å¿ èŠã«å¿ããŠé åèªã䜿çšãã
XML ãªã©ã®é åèªã¯çç¥åœ¢ã§ã¯ãªãã.NET ã©ã€ãã©ãª (Xml) ã§åºã䜿çšãããŠããŸãã ããç¥ãããŠãããåºãèªèãããŠããé åèªã®ã¿ã䜿çšããå¿ èŠããããŸãã
ãžã§ããªã㯠ãã©ã¡ãŒã¿ãŒåã« PascalCase ã䜿çšãã
ãããªã㯠API ã®ãžã§ããªã㯠ãã©ã¡ãŒã¿ãŒåã«ã¯ PascalCase ã䜿çšããŠãã ãã (F# ã«æ¥ç¶ããã©ã€ãã©ãªãå«ã)ã ç¹ã«ãä»»æã®ãžã§ããªã㯠ãã©ã¡ãŒã¿ãŒã«ã¯ TãUãT1ãT2 ãªã©ã®ååã䜿çšããç¹å®ã®ååãæå³ãæã€å Žåã¯ãF# ã«æ¥ç¶ããã©ã€ãã©ãªã§ã¯ãKeyãValueãArg ãªã©ã®ååã䜿çšããŸã (TKeyãªã©ã§ã¯ãããŸãã)ã
F# ã¢ãžã¥ãŒã«ã®ãããªãã¯é¢æ°ãšå€ã« PascalCase ãŸã㯠camelCase ã䜿çšãã
camelCase ã¯ã修食ãããŠããªã (ããšãã°ãinvalidArg) 䜿çšããããã«èšèšããããããªãã¯é¢æ°ãšã"æšæºã³ã¬ã¯ã·ã§ã³é¢æ°" (List.map ãªã©) ã«äœ¿çšãããŸãã ã©ã¡ãã®å Žåãã颿°åã¯èšèªã®ããŒã¯ãŒããšãã䌌ãŠããŸãã
ãªããžã§ã¯ããåãããã³ã¢ãžã¥ãŒã«ã®èšèš
åå空éãŸãã¯ã¢ãžã¥ãŒã«ã䜿çšããŠåãšã¢ãžã¥ãŒã«ãå«ãã
ã³ã³ããŒãã³ãå ã®å F# ãã¡ã€ã«ã¯ãåå空é宣èšãŸãã¯ã¢ãžã¥ãŒã«å®£èšã§å§ãŸãå¿ èŠããããŸãã
namespace Fabrikam.BasicOperationsAndTypes
type ObjectType1() =
...
type ObjectType2() =
...
module CommonOperations =
...
ãŸãã¯
module Fabrikam.BasicOperationsAndTypes
type ObjectType1() =
...
type ObjectType2() =
...
module CommonOperations =
...
ã¢ãžã¥ãŒã«ãšåå空éã䜿çšããŠæäžäœã¬ãã«ã§ã³ãŒããæŽçããå Žåã®éãã¯æ¬¡ã®ãšããã§ãã
- åå空éã¯è€æ°ã®ãã¡ã€ã«ã«ãŸãããããšãã§ããŸã
- å éšã¢ãžã¥ãŒã«å ã«ååšããªãéããåå空éã« F# 颿°ãå«ããããšã¯ã§ããŸãã
- ç¹å®ã®ã¢ãžã¥ãŒã«ã®ã³ãŒãã¯ã1 ã€ã®ãã¡ã€ã«å ã«å«ãŸããŠããå¿ èŠããããŸã
- æäžäœã¢ãžã¥ãŒã«ã«ã¯ãå éšã¢ãžã¥ãŒã«ãå¿ èŠãšããã« F# 颿°ãå«ããããšãã§ããŸã
æäžäœã¬ãã«ã®åå空éãŸãã¯ã¢ãžã¥ãŒã«ã®ã©ã¡ããéžæãããã¯ãã³ãŒãã®ã³ã³ãã€ã«æžã¿ã®åœ¢åŒã«åœ±é¿ãããããæçµçã« API ã F# ã³ãŒãã®å€éšã§äœ¿çšãããå Žåã¯ãä»ã® .NET èšèªããã®ãã¥ãŒã«åœ±é¿ããŸãã
ãªããžã§ã¯ãåã«åºæã®æäœã«ã¯ã¡ãœãããšããããã£ã䜿çšãã
ãªããžã§ã¯ããæäœããå Žåã¯ããã®åã®ã¡ãœãããšããããã£ãšããŠæ¶èåæ©èœãå®è£ ãããŠããããšã確èªããããšããå§ãããŸãã
type HardwareDevice() =
member this.ID = ...
member this.SupportedProtocols = ...
type HashTable<'Key,'Value>(comparer: IEqualityComparer<'Key>) =
member this.Add(key, value) = ...
member this.ContainsKey(key) = ...
member this.ContainsValue(value) = ...
ç¹å®ã®ã¡ã³ããŒã®æ©èœã®å€§éšåãå¿ ããããã®ã¡ã³ããŒã«å®è£ ããå¿ èŠã¯ãããŸãããããã®æ©èœã®äžéšã¯æ¶èåã§ããå¿ èŠããããŸãã
ã¯ã©ã¹ã䜿çšããŠå€æŽå¯èœãªç¶æ ãã«ãã»ã«åãã
F# ã§ã¯ããã®æäœã¯ãã¯ããŒãžã£ãã·ãŒã±ã³ã¹åŒãéåæèšç®ãªã©ãå¥ã®èšèªã³ã³ã¹ãã©ã¯ãã«ãã£ãŠãã®ç¶æ ããŸã ã«ãã»ã«åãããŠããªãå Žåã«ã®ã¿è¡ãå¿ èŠããããŸãã
type Counter() =
// let-bound values are private in classes.
let mutable count = 0
member this.Next() =
count <- count + 1
count
ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠé¢é£ããæäœãã°ã«ãŒãåãã
ã€ã³ã¿ãŒãã§ã€ã¹åã䜿çšããŠãäžé£ã®æäœã衚ããŸãã ããã¯ã颿°ã®ã¿ãã«ã颿°ã®ã¬ã³ãŒããªã©ãä»ã®ãªãã·ã§ã³ã«é©ããŠããŸãã
type Serializer =
abstract Serialize<'T> : preserveRefEq: bool -> value: 'T -> string
abstract Deserialize<'T> : preserveRefEq: bool -> pickle: string -> 'T
æšå¥šãããªãäŸ:
type Serializer<'T> = {
Serialize: bool -> 'T -> string
Deserialize: bool -> string -> 'T
}
ã€ã³ã¿ãŒãã§ã€ã¹ã¯ .NET ã®æäžäœã®æŠå¿µã§ãããFunctor ãéåžžæäŸãããã®ãå®çŸããããã«äœ¿çšã§ããŸãã ããã«ãããã°ã©ã ã§é¢æ°ã®ã¬ã³ãŒãã§ã¯ã§ããªãååšåããšã³ã³ãŒãããããã«äœ¿çšã§ããŸãã
ã¢ãžã¥ãŒã«ã䜿çšããŠã³ã¬ã¯ã·ã§ã³ã«äœçšãã颿°ãã°ã«ãŒãåãã
ã³ã¬ã¯ã·ã§ã³åãå®çŸ©ããå Žåã¯ãæ°ããã³ã¬ã¯ã·ã§ã³åã® CollectionType.map ã CollectionType.iter) ãªã©ã®æšæºã®æäœã»ãããæäŸããããšãæ€èšããŠãã ããã
module CollectionType =
let map f c =
...
let iter f c =
...
ãã®ãããªã¢ãžã¥ãŒã«ãå«ããå Žåã¯ãFSharp.Core ã§èŠã€ãã£ã颿°ã®æšæºã®ååä»ãèŠåã«åŸããŸãã
ã¢ãžã¥ãŒã«ã䜿çšããŠãäžè¬çãªæ£èŠé¢æ° (ç¹ã«æ°åŠããã³ DSL ã©ã€ãã©ãª) ã®é¢æ°ãã°ã«ãŒãåãã
ããšãã°ãMicrosoft.FSharp.Core.Operators ã¯ãFSharp.Core.dllã«ãã£ãŠæäŸãããæäžäœã®é¢æ° (abs ã sinãªã©) ã®èªåçã«éãããã³ã¬ã¯ã·ã§ã³ã§ãã
åæ§ã«ãçµ±èšã©ã€ãã©ãªã«ã¯ã颿° erf ãš erfcãå«ãã¢ãžã¥ãŒã«ãå«ãŸããå ŽåããããŸãããã®ã¢ãžã¥ãŒã«ã¯ãæç€ºçãŸãã¯èªåçã«éãããããã«èšèšãããŠããŸãã
RequireQualifiedAccess ã®äœ¿çšãæ€èšããAutoOpen 屿§ãæ éã«é©çšãã
ã¢ãžã¥ãŒã«ã« [<RequireQualifiedAccess>] 屿§ã远å ãããšãã¢ãžã¥ãŒã«ãéãããšãã§ããªãå¯èœæ§ããããã¢ãžã¥ãŒã«ã®èŠçŽ ãžã®åç
§ã«ã¯æç€ºçãªä¿®é£Ÿã¢ã¯ã»ã¹ãå¿
èŠã§ããããšã瀺ãããŸãã ããšãã°ãMicrosoft.FSharp.Collections.List ã¢ãžã¥ãŒã«ã«ã¯ãã®å±æ§ããããŸãã
ããã¯ãã¢ãžã¥ãŒã«å ã®é¢æ°ãšå€ã®ååãä»ã®ã¢ãžã¥ãŒã«ã®ååãšç«¶åããå¯èœæ§ãããå Žåã«äŸ¿å©ã§ãã 修食ãããã¢ã¯ã»ã¹ãèŠæ±ãããšãã©ã€ãã©ãªã®é·æçãªä¿å®æ§ãšé²åæ§ãå€§å¹ ã«åäžããå¯èœæ§ããããŸãã
[<RequireQualifiedAccess>] ã«ãã£ãŠæäŸãããã¢ãžã¥ãŒã« (FSharp.CoreãSeqãListãªã©) ãæ¡åŒµããã«ã¹ã¿ã ã¢ãžã¥ãŒã«ã® Array 屿§ã¯ãF# ã³ãŒãã§äžè¬çã«äœ¿çšããã[<RequireQualifiedAccess>] å®çŸ©ãããŠããããã匷ããå§ãããŸããããäžè¬çã«ã¯ããã®ãããªã¢ãžã¥ãŒã«ãã·ã£ããŠãããã屿§ãæã€ä»ã®ã¢ãžã¥ãŒã«ãæ¡åŒµãããããå Žåã¯ã屿§ãæããªãã«ã¹ã¿ã ã¢ãžã¥ãŒã«ãå®çŸ©ããããšã¯ãå§ãããŸããã
[<AutoOpen>] 屿§ãã¢ãžã¥ãŒã«ã«è¿œå ãããšãå«ãŸããŠããåå空éãéããããšãã«ã¢ãžã¥ãŒã«ãéãããŸãã
[<AutoOpen>] 屿§ãã¢ã»ã³ããªã«é©çšããŠãã¢ã»ã³ããªãåç
§ããããšãã«èªåçã«éãããã¢ãžã¥ãŒã«ã瀺ãããšãã§ããŸãã
ããšãã°ãMathsHeaven.Statistics çµ±èšã©ã€ãã©ãªã«ã¯ãmodule MathsHeaven.Statistics.Operators ããã³ erf颿°ãå«ã erfc ãå«ãŸããŠããå ŽåããããŸãã ãã®ã¢ãžã¥ãŒã«ã [<AutoOpen>]ãšããŠããŒã¯ããããšã¯åŠ¥åœã§ãã ã€ãŸããopen MathsHeaven.Statistics ããã®ã¢ãžã¥ãŒã«ãéããåå erf ãš erfc ãã¹ã³ãŒãã«åã蟌ã¿ãŸãã
[<AutoOpen>] ã®ãã 1 ã€ã®åªããçšéã¯ãæ¡åŒµã¡ãœãããå«ãã¢ãžã¥ãŒã«ã§ãã
[<AutoOpen>] ã®éå°äœ¿çšã¯ãæ±æãããåå空éã«ã€ãªããã®ã§ã屿§ã¯æ
éã«äœ¿çšããå¿
èŠããããŸãã ç¹å®ã®ãã¡ã€ã³å
ã®ç¹å®ã®ã©ã€ãã©ãªã§ã¯ã[<AutoOpen>] ãæ
éã«äœ¿çšãããšã䜿ãããããåäžããå¯èœæ§ããããŸãã
æ¢ç¥ã®æŒç®åã䜿çšããããšãé©åãªã¯ã©ã¹ã§æŒç®åã¡ã³ããŒãå®çŸ©ããããšãæ€èšãã
Vector ãªã©ã®æ°åŠçæ§é ãã¢ãã«åããããã«ã¯ã©ã¹ã䜿çšãããå ŽåããããŸãã ã¢ãã«åããããã¡ã€ã³ã«æ¢ç¥ã®æŒç®åãããå Žåã¯ãã¯ã©ã¹ã«çµã¿èŸŒãŸããŠããã¡ã³ããŒãšããŠå®çŸ©ãããšäŸ¿å©ã§ãã
type Vector(x: float) =
member v.X = x
static member (*) (vector: Vector, scalar: float) = Vector(vector.X * scalar)
static member (+) (vector1: Vector, vector2: Vector) = Vector(vector1.X + vector2.X)
let v = Vector(5.0)
let u = v * 10.0
ãã®ã¬ã€ãã³ã¹ã¯ããããã®åã®äžè¬ç㪠.NET ã¬ã€ãã³ã¹ã«å¯Ÿå¿ããŠããŸãã ãã ããF# ã³ãŒãã£ã³ã°ã§ã¯ããããã®åã F# 颿°ãã¡ã³ããŒå¶çŽãæã€ã¡ãœãã (List.sumBy ãªã©) ãšçµã¿åãããŠäœ¿çšã§ãããããããã«éèŠãªå ŽåããããŸãã
ä»ã® .NET èšèªã®å©çšè ã«å¯ŸããŠã.NET ã§æ±ããããååãæäŸããããã«ãCompiledName ã䜿çšããããšãæ€èšããŠãã ããã
å Žåã«ãã£ãŠã¯ãF# ã³ã³ã·ã¥ãŒããŒçšã« 1 ã€ã®ã¹ã¿ã€ã«ã§ååãä»ããããšãã§ããŸã (ããšãã°ãã¢ãžã¥ãŒã« ãã€ã³ã颿°ã®ããã«èŠããããã«ãå°æåã®éçã¡ã³ããŒãªã©)ãã¢ã»ã³ããªã«ã³ã³ãã€ã«ããããšãã«ååã®ã¹ã¿ã€ã«ãç°ãªãå ŽåããããŸãã
[<CompiledName>] 屿§ã䜿çšããŠãã¢ã»ã³ããªã䜿çšãã F# 以å€ã®ã³ãŒãã«å¥ã®ã¹ã¿ã€ã«ãæå®ã§ããŸãã
type Vector(x:float, y:float) =
member v.X = x
member v.Y = y
[<CompiledName("Create")>]
static member create x y = Vector (x, y)
let v = Vector.create 5.0 3.0
[<CompiledName>]ã䜿çšãããšãã¢ã»ã³ããªã® F# 以å€ã®ã³ã³ã·ã¥ãŒããŒã«å¯Ÿã㊠.NET ååä»ãèŠåã䜿çšã§ããŸãã
ã¡ã³ããŒé¢æ°ã®ã¡ãœãã ãªãŒããŒããŒãã䜿çšããŸãããããããšãããåçŽãª API ãæäŸãããŸã
ã¡ãœããã®ãªãŒããŒããŒãã¯ãåæ§ã®æ©èœãå®è¡ããå¿ èŠãããå ŽåããããŸãããããŸããŸãªãªãã·ã§ã³ãåŒæ°ã䜿çšã㊠API ãç°¡ç¥åããããã®åŒ·åãªããŒã«ã§ãã
type Logger() =
member this.Log(message) =
...
member this.Log(message, retryPolicy) =
...
F# ã§ã¯ãåŒæ°ã®åã§ã¯ãªããåŒæ°ã®æ°ããªãŒããŒããŒãããæ¹ãäžè¬çã§ãã
èšèšãé²åããå¯èœæ§ãé«ãå Žåã¯ãã¬ã³ãŒãåãšãŠããªã³åã®è¡šçŸãé衚瀺ã«ãã
ãªããžã§ã¯ãã®å ·äœçãªè¡šçŸã衚瀺ããªãããã«ããŸãã ããšãã°ãDateTime å€ã®å ·äœçãªè¡šçŸã¯ã.NET ã©ã€ãã©ãª ãã¶ã€ã³ã®å€éšã®ãããªã㯠API ã§ã¯è¡šç€ºãããŸããã å®è¡æã«ãå ±éèšèªã©ã³ã¿ã€ã ã¯ãå®è¡å šäœã§äœ¿çšãããã³ãããæžã¿ã®å®è£ ãèªèããŸãã ãã ããã³ã³ãã€ã«ãããã³ãŒãèªäœã¯ãå ·è±¡è¡šçŸãžã®äŸåé¢ä¿ãååŸããŸããã
æ¡åŒµã®ããã«å®è£ ç¶æ¿ã䜿çšããªãããã«ãã
F# ã§ã¯ãå®è£ ã®ç¶æ¿ã¯ã»ãšãã©äœ¿çšããŸããã ããã«ãç¶æ¿éå±€ã¯ãå€ãã®å Žåãè€éã§ãæ°ããèŠä»¶ãå°çãããšãã«å€æŽãå°é£ã§ãã äºææ§ããŸããªã±ãŒã¹ã§ã¯ãåé¡ã«å¯Ÿããæåã®è§£æ±ºçãšããŠç¶æ¿ã®å®è£ ã F# ã«ååšããŸãããã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ãªã©ã®å€åãèšèšããå Žåã¯ãF# ããã°ã©ã ã§ä»£æ¿ææ³ãæ€èšããå¿ èŠããããŸãã
颿°ãšã¡ã³ããŒã®ã·ã°ããã£
æ»ãå€ãšããŠå°æ°ã®é¢é£ã®ãªãå€ãè¿ãå Žåã«ã¯ãã¿ãã«ã䜿çšããŠãã ããã
æ»ãå€ã®åã§ã¿ãã«ã䜿çšããè¯ãäŸã次ã«ç€ºããŸãã
val divrem: BigInteger -> BigInteger -> BigInteger * BigInteger
å€ãã®ã³ã³ããŒãã³ããå«ãæ»ãå€ã®åããŸãã¯ã³ã³ããŒãã³ãã 1 ã€ã®èå¥å¯èœãªãšã³ãã£ãã£ã«é¢é£ããŠããå Žåã¯ãã¿ãã«ã§ã¯ãªãååä»ãåã䜿çšããããšãæ€èšããŠãã ããã
F# API å¢çã§ã®éåæããã°ã©ãã³ã°ã« Async<T> ã䜿çšãã
Operationãè¿ã T ãšããååã®å¯Ÿå¿ããåææäœãããå Žåã¯ãéåææäœã AsyncOperation ãè¿ãå Žå㯠Async<T>ãOperationAsyncãè¿ãå Žå㯠Task<T> ããå¿
èŠããããŸãã Begin/End ã¡ãœãããå
¬éããäžè¬çã«äœ¿çšããã .NET åã®å Žåã¯ãAsync.FromBeginEnd ã䜿çšããŠæ¡åŒµã¡ãœããããã¡ãµãŒããšããŠèšè¿°ãããããã® .NET API ã« F# éåæããã°ã©ãã³ã° ã¢ãã«ãæäŸããããšãæ€èšããŠãã ããã
type SomeType =
member this.Compute(x:int): int =
...
member this.AsyncCompute(x:int): Async<int> =
...
type System.ServiceModel.Channels.IInputChannel with
member this.AsyncReceive() =
...
äŸå€
äŸå€ãçµæãããã³ãªãã·ã§ã³ã®é©åãªäœ¿ç𿹿³ã«ã€ããŠã¯ãããšã©ãŒç®¡çã®ããåç §ããŠãã ããã
æ¡åŒµã¡ã³ããŒ
F# å士ã®ã³ã³ããŒãã³ããžã® F# æ¡åŒµã¡ã³ããŒã®é©çšã¯æ éã«ãã
F# æ¡åŒµã¡ã³ããŒã¯ãéåžžããã®äœ¿çšã¢ãŒãã®å€§éšåã§åã«é¢é£ä»ããããŠããçµã¿èŸŒã¿æäœã®çµäºäžã®æäœã«ã®ã¿äœ¿çšããå¿ èŠããããŸãã äžè¬çãªçšéã® 1 ã€ã¯ãããŸããŸãª .NET åã«å¯Ÿã㊠F# ã«æ £çšç㪠API ãæäŸããæ¹æ³ã§ãã
type System.ServiceModel.Channels.IInputChannel with
member this.AsyncReceive() =
Async.FromBeginEnd(this.BeginReceive, this.EndReceive)
type System.Collections.Generic.IDictionary<'Key,'Value> with
member this.TryGet key =
let ok, v = this.TryGetValue key
if ok then Some v else None
å ±çšäœå
ããªãŒæ§é ããŒã¿ã®ã¯ã©ã¹éå±€ã®ä»£ããã«å€å¥å ±çšäœã䜿çšãã
ããªãŒã®ãããªæ§é äœã¯ååž°çã«å®çŸ©ãããŸãã ããã¯ç¶æ¿ã«ã¯äžäŸ¿ã§ãããå€å¥å ±çšäœã«ã¯æŽç·ŽãããŠããŸãã
type BST<'T> =
| Empty
| Node of 'T * BST<'T> * BST<'T>
ãã£ã¹ã¯ãªãããŒãã£ãããŠããªã³ã䜿çšããŠæšæ§é ã®ããŒã¿ã衚çŸãããšããã¿ãŒã³ãããã³ã°ã§ç¶²çŸ æ§ã®ã¡ãªãããåŸãããŸãã
ã±ãŒã¹åãååã«äžæã§ãªãå
±çšäœåã«ã¯ [<RequireQualifiedAccess>] ã䜿çšãã
å€å¥å
±çšäœã®ã±ãŒã¹ã®ããã«ãåãååããå¥ã®ãã®ã«ã¯æé©ãªååã«ãªããã¡ã€ã³ãããããšã«æ°ä»ãããšããããŸãã
[<RequireQualifiedAccess>] ã䜿çšããŠã±ãŒã¹åãæç¢ºã«ããããšã§ãopen ã¹ããŒãã¡ã³ãã®é åºã«äŸåããã·ã£ããŠã€ã³ã°ã«ãã£ãŠçºçããæ··ä¹±ãæããšã©ãŒãé²ãããšãã§ããŸãã
ãããã®åã®èšèšãé²åããå¯èœæ§ãé«ãå Žåã¯ããã€ããªäºæ API ã®å€å¥å ±çšäœã®è¡šçŸãé衚瀺ã«ãã
ãŠããªã³åã¯ãç°¡æœãªããã°ã©ãã³ã°ã¢ãã«ãå®çŸããããã«ãF#ã®ãã¿ãŒã³ãããã³ã°æ§æã䜿çšããŸãã åè¿°ã®ããã«ããããã®åã®èšèšãé²åããå¯èœæ§ãé«ãå Žåã¯ãå ·äœçãªããŒã¿è¡šçŸãæããã«ããªãããã«ããå¿ èŠããããŸãã
ããšãã°ãå€å¥å ±çšäœã®è¡šçŸã¯ãéå ¬éãŸãã¯å éšã®å®£èšã䜿çšããããã·ã°ãã㣠ãã¡ã€ã«ã䜿çšããŠé ãããšãã§ããŸãã
type Union =
private
| CaseA of int
| CaseB of string
å€å¥å ±çšäœãç¡å·®å¥ã«æããã«ãããšããŠãŒã¶ãŒ ã³ãŒããå£ãããšãªãã©ã€ãã©ãªã®ããŒãžã§ã³ã管çããããšãå°é£ã«ãªãå¯èœæ§ããããŸãã 代ããã«ã1 ã€ä»¥äžã®ã¢ã¯ãã£ããªãã¿ãŒã³ãæããã«ããŠãåã®å€ã«å¯Ÿãããã¿ãŒã³ ãããã³ã°ãèš±å¯ããããšãæ€èšããŠãã ããã
ã¢ã¯ãã£ã ãã¿ãŒã³ã¯ãF# å ±çšäœåãçŽæ¥å ¬éããããšãåé¿ããªãããF# ã³ã³ã·ã¥ãŒããŒã«ãã¿ãŒã³ ãããã³ã°ãæäŸããå¥ã®æ¹æ³ãæäŸããŸãã
ã€ã³ã©ã€ã³é¢æ°ãšã¡ã³ããŒå¶çŽ
æé»çãªã¡ã³ããŒå¶çŽãšéçã«è§£æ±ºããããžã§ããªãã¯åãæã€ã€ã³ã©ã€ã³é¢æ°ã䜿çšããŠãžã§ããªãã¯æ°å€ã¢ã«ãŽãªãºã ãå®çŸ©ãã
ç®è¡ã¡ã³ããŒå¶çŽãš F# æ¯èŒå¶çŽã¯ãF# ããã°ã©ãã³ã°ã®æšæºã§ãã ããšãã°ã次ã®ã³ãŒããèããŠã¿ãŸãããã
let inline highestCommonFactor a b =
let rec loop a b =
if a = LanguagePrimitives.GenericZero<_> then b
elif a < b then loop a (b - a)
else loop (a - b) b
loop a b
ãã®é¢æ°ã®åã¯æ¬¡ã®ãšããã§ãã
val inline highestCommonFactor : ^T -> ^T -> ^T
when ^T : (static member Zero : ^T)
and ^T : (static member ( - ) : ^T * ^T -> ^T)
and ^T : equality
and ^T : comparison
ããã¯ãæ°åŠã©ã€ãã©ãªã®ãããªã㯠API ã«é©ãã颿°ã§ãã
åã¯ã©ã¹ãšãã㯠ã¿ã€ãã³ã°ãã·ãã¥ã¬ãŒãããããã«ã¡ã³ããŒå¶çŽã䜿çšããªã
F# ã¡ã³ããŒå¶çŽã䜿çšããŠã"duck typing" ãã·ãã¥ã¬ãŒãã§ããŸãã ãã ãããããå©çšããã¡ã³ããŒã¯ãéåžžãF# å士ã®ã©ã€ãã©ãª ãã¶ã€ã³ã«ã¯äœ¿çšããªãã§ãã ããã ããã¯ãæªç¥ã®æé»çå¶çŽãŸãã¯éæšæºã®æé»çå¶çŽã«åºã¥ãã©ã€ãã©ãª èšèšã§ã¯ããŠãŒã¶ãŒ ã³ãŒããæè»æ§ãæããªããªããç¹å®ã®ãã¬ãŒã ã¯ãŒã¯ ãã¿ãŒã³ã«é¢é£ä»ããããŠããåŸåãããããã§ãã
ããã«ããã®æ¹æ³ã§ã¡ã³ããŒå¶çŽãé »ç¹ã«äœ¿çšãããšãã³ã³ãã€ã«æéãéåžžã«é·ããªãããšããããŸãã
æŒç®åã®å®çŸ©
ã«ã¹ã¿ã ã·ã³ããªãã¯æŒç®åã®å®çŸ©ãé¿ãã
ã«ã¹ã¿ã æŒç®åã¯ç¶æ³ã«ãã£ãŠã¯äžå¯æ¬ ã§ãããå®è£ ã³ãŒãã®å€§èŠæš¡ãªæ¬æå ã§éåžžã«äŸ¿å©ãªè¡šèšããã€ã¹ã§ãã ã©ã€ãã©ãªã®æ°ãããŠãŒã¶ãŒã®å Žåãååä»ã颿°ã®æ¹ã䜿ããããããšããããããŸãã ããã«ãã«ã¹ã¿ã ã·ã³ããªãã¯æŒç®åã¯ææžåããã®ãé£ããå ŽåããããIDE ãšæ€çŽ¢ãšã³ãžã³ã®æ¢åã®å¶éã«ããããŠãŒã¶ãŒã¯æŒç®åã®ãã«ããæ€çŽ¢ããã®ãé£ãããªããŸãã
ãã®çµæãæ©èœãååä»ã颿°ããã³ã¡ã³ããŒãšããŠå ¬éããããã«ã衚èšäžã®å©ç¹ãããããæã€ããšã®ããã¥ã¡ã³ããšã³ã°ããã£ã ã³ã¹ããäžåãå Žåã«ã®ã¿ããã®æ©èœã®æŒç®åãå ¬éããããšããå§ãããŸãã
枬å®åäœ
F# ã³ãŒãã«ãããåã®å®å šæ§ãé«ããããã«ãåäœãæ éã«äœ¿çšãã
ä»ã® .NET èšèªã§è¡šç€ºãããšã枬å®åäœã«é¢ãã远å ã®å
¥åæ
å ±ã¯æ¶å»ãããŸãã .NET ã³ã³ããŒãã³ããããŒã«ãããã³ãªãã¬ã¯ã·ã§ã³ã§ã¯ãåäœãªãã®åã衚瀺ãããããšã«æ³šæããŠãã ããã ããšãã°ãC# ã³ã³ã·ã¥ãŒããŒã«ã¯ãfloatã§ã¯ãªã float<kg> ã衚瀺ãããŸãã
åç¥ç§°
åã®çç¥åœ¢ãæ éã«äœ¿çšã㊠F# ã³ãŒããç°¡ç¥åãã
.NET ã³ã³ããŒãã³ããããŒã«ããªãã¬ã¯ã·ã§ã³ã«ã¯ãåã®çç¥åã¯è¡šç€ºãããŸããã åã®çç¥åœ¢ãå€§å¹ ã«äœ¿çšãããšããã¡ã€ã³ãå®éãããè€éã«èŠããå¯èœæ§ããããã³ã³ã·ã¥ãŒããŒãæ··ä¹±ãããå¯èœæ§ããããŸãã
ã¡ã³ããŒãšããããã£ããçç¥ãããŠããåã§äœ¿çšã§ãããã®ãšæ¬è³ªçã«ç°ãªãå Žåããããªãã¯åã«ã¯åã®çç¥åœ¢ã䜿çšããªã
ãã®å Žåãçç¥ãããåã¯ãå®çŸ©ãããŠããå®éã®åã®è¡šçŸã«é¢ããŠããŸãã«ãå€ããæããã«ããŸãã 代ããã«ãçç¥åœ¢ãã¯ã©ã¹åãŸãã¯åäžã±ãŒã¹ã®å€å¥å ±çšäœã§ã©ããããããšãæ€èšããŠãã ãã (ãŸãã¯ãããã©ãŒãã³ã¹ãäžå¯æ¬ ãªå Žåã¯ãæ§é äœåã䜿çšããŠçç¥åœ¢ãã©ããããããšãæ€èšããŠãã ãã)ã
ããšãã°ãF# ãããã®ç¹æ®ãªã±ãŒã¹ãšããŠãã«ãããããå®çŸ©ããããªãå ŽåããããŸããæ¬¡ã«äŸã瀺ããŸãã
type MultiMap<'Key,'Value> = Map<'Key,'Value list>
ãã ãããã®åã«å¯Ÿããè«çãããè¡šèšæŒç®ã¯ãMap ã§ã®æäœãšåãã§ã¯ãããŸãããããšãã°ãããŒããã£ã¯ã·ã§ããªã«ãªãå Žåã¯ãã«ãã¯ã¢ããæŒç®å map[key] 空ã®ãªã¹ããè¿ãã®ã劥åœã§ããäŸå€ãçºçãããã®ã§ã¯ãªãããŸãã
ä»ã® .NET èšèªãã䜿çšããããã®ã©ã€ãã©ãªã®ã¬ã€ãã©ã€ã³
ä»ã® .NET èšèªãã䜿çšããã©ã€ãã©ãªãèšèšããå Žåã¯ã.NET ã©ã€ãã©ãªèšèšã¬ã€ãã©ã€ã³ã«åŸãããšãéèŠã§ãã ãã®ããã¥ã¡ã³ãã§ã¯ããããã®ã©ã€ãã©ãªã¯ãF# ã³ã³ã¹ãã©ã¯ããå¶éãªãã§äœ¿çšãã F# åãã©ã€ãã©ãªãšã¯å¯Ÿç §çã«ãããã© .NET ã©ã€ãã©ãªãšããŠã©ãã«ä»ããããŠããŸãã ããã© .NET ã©ã€ãã©ãªãèšèšããããšã¯ããããªã㯠API ã§ã® F# åºæã®ã³ã³ã¹ãã©ã¯ãã®äœ¿çšãæå°éã«æããããšã§ã.NET Framework ã®æ®ãã®éšåãšäžè²«æ§ã®ããäœ¿ãæ £ããæ £çš API ãæäŸããããšãæå³ããŸãã èŠåã«ã€ããŠã¯ã次ã®ã»ã¯ã·ã§ã³ã§èª¬æããŸãã
åå空éãšåã®èšèš (ä»ã® .NET èšèªãã䜿çšããã©ã€ãã©ãªçš)
ã³ã³ããŒãã³ãã®ãããªã㯠API ã« .NET ååä»ãèŠåãé©çšãã
çç¥åãš .NET ã®å€§æåãšå°æåã®ã¬ã€ãã©ã€ã³ã®äœ¿çšã«ç¹ã«æ³šæããŠãã ããã
type pCoord = ...
member this.theta = ...
type PolarCoordinate = ...
member this.Theta = ...
ã³ã³ããŒãã³ãã®äž»èŠãªçµç¹æ§é ãšããŠåå空éãåãããã³ã¡ã³ããŒã䜿çšãã
ãããªãã¯æ©èœãå«ããã¹ãŠã®ãã¡ã€ã«ã¯ namespace 宣èšã§å§ãŸãå¿
èŠããããåå空éå
ã®å
¬éãšã³ãã£ãã£ã¯åã®ã¿ã§ããå¿
èŠããããŸãã F# ã¢ãžã¥ãŒã«ã¯äœ¿çšããªãã§ãã ããã
éãããªã㯠ã¢ãžã¥ãŒã«ã䜿çšããŠãå®è£ ã³ãŒãããŠãŒãã£ãªãã£åãããã³ãŠãŒãã£ãªãã£é¢æ°ãä¿æããŸãã
éçåã¯ã¢ãžã¥ãŒã«ãããåªå ããå¿ èŠããããŸããããã«ãããAPI ã®å°æ¥ã®é²åã«ãã£ãŠãF# ã¢ãžã¥ãŒã«å ã§ã¯äœ¿çšã§ããªãå¯èœæ§ã®ãããªãŒããŒããŒãããã®ä»ã® .NET API èšèšæŠå¿µã䜿çšã§ããããã«ãªããŸãã
ããšãã°ã次ã®ãããªã㯠API ã®ä»£ããã«ã
module Fabrikam
module Utilities =
let Name = "Bob"
let Add2 x y = x + y
let Add3 x y z = x + y + z
代ããã«æ¬¡ã®ããšãæ€èšããŠãã ããã
namespace Fabrikam
[<AbstractClass; Sealed>]
type Utilities =
static member Name = "Bob"
static member Add(x,y) = x + y
static member Add(x,y,z) = x + y + z
åã®èšèšãé²åããªãå Žåã¯ãããã© .NET API ã§ F# ã¬ã³ãŒãåã䜿çšãã
F# ã¬ã³ãŒãåã¯ãåçŽãª .NET ã¯ã©ã¹ã«ã³ã³ãã€ã«ãããŸãã ãããã¯ãAPI ã®äžéšã®åçŽã§å®å®ããåã«é©ããŠããŸãã
[<NoEquality>] 屿§ãš [<NoComparison>] 屿§ã䜿çšããŠãã€ã³ã¿ãŒãã§ã€ã¹ã®èªåçæãæå¶ããããšãæ€èšããŠãã ããã ãŸãããããªã㯠ãã£ãŒã«ããå
¬éããããããããã© .NET API ã§å€æŽå¯èœãªã¬ã³ãŒã ãã£ãŒã«ãã䜿çšããããšã¯é¿ããŠãã ããã ã¯ã©ã¹ã API ã®å°æ¥ã®é²åã«å¯ŸããŠããæè»ãªãªãã·ã§ã³ãæäŸãããã©ãããåžžã«æ€èšããŠãã ããã
ããšãã°ã次㮠F# ã³ãŒãã¯ããããªã㯠API ã C# ã³ã³ã·ã¥ãŒããŒã«å ¬éããŸãã
F#:
[<NoEquality; NoComparison>]
type MyRecord =
{ FirstThing: int
SecondThing: string }
C#:
public sealed class MyRecord
{
public MyRecord(int firstThing, string secondThing);
public int FirstThing { get; }
public string SecondThing { get; }
}
æšæºã® .NET API ã§ F# å ±çšäœã®è¡šçŸãé衚瀺ã«ãã
F# å ±çšäœã®åã¯ãF#ãã F# ãžã®ã³ãŒãã£ã³ã°ã®å Žåã§ããã³ã³ããŒãã³ãã®å¢çãè¶ããŠäžè¬çã«äœ¿çšãããŸããã ãããã¯ãã³ã³ããŒãã³ããšã©ã€ãã©ãªå ã§å éšçã«äœ¿çšããå Žåã«åªããå®è£ ããã€ã¹ã§ãã
ããã© .NET API ãèšèšããå Žåã¯ããã©ã€ããŒã宣èšãŸãã¯çœ²åãã¡ã€ã«ã䜿çšããŠãå ±çšäœã®åã®è¡šçŸãé衚瀺ã«ããããšãæ€èšããŠãã ããã
type PropLogic =
private
| And of PropLogic * PropLogic
| Not of PropLogic
| True
ãŸããå éšã§å ±çšäœè¡šçŸã䜿çšããŠããåãã¡ã³ããŒã䜿çšããŠæ¡åŒµããŠãç®çã® .NET å¯Ÿå¿ API ãçšæããããšãã§ããŸãã
type PropLogic =
private
| And of PropLogic * PropLogic
| Not of PropLogic
| True
/// A public member for use from C#
member x.Evaluate =
match x with
| And(a,b) -> a.Evaluate && b.Evaluate
| Not a -> not a.Evaluate
| True -> true
/// A public member for use from C#
static member CreateAnd(a,b) = And(a,b)
ãã¬ãŒã ã¯ãŒã¯ã®èšèšãã¿ãŒã³ã䜿çšã㊠GUI ããã®ä»ã®ã³ã³ããŒãã³ããèšèšãã
.NET ã«ã¯ãWinFormsãWPFãASP.NET ãªã©ãããŸããŸãªãã¬ãŒã ã¯ãŒã¯ããããŸãã ãããã®ãã¬ãŒã ã¯ãŒã¯ã§äœ¿çšããã³ã³ããŒãã³ããèšèšããå Žåã¯ãããããã®ååä»ãèŠåãšèšèšèŠåã䜿çšããå¿ èŠããããŸãã ããšãã°ãWPF ããã°ã©ãã³ã°ã®å Žåã¯ãèšèšããã¯ã©ã¹ã« WPF ãã¶ã€ã³ ãã¿ãŒã³ãæ¡çšããŸãã ãŠãŒã¶ãŒ ã€ã³ã¿ãŒãã§ã€ã¹ ããã°ã©ãã³ã°ã®ã¢ãã«ã®å Žåã¯ãã€ãã³ããéç¥ããŒã¹ã®ã³ã¬ã¯ã·ã§ã³ãªã©ã®èšèšãã¿ãŒã³ (System.Collections.ObjectModelã§èŠã€ãã£ããã®ãªã©) ã䜿çšããŸãã
ãªããžã§ã¯ããšã¡ã³ããŒã®ãã¶ã€ã³ (ä»ã® .NET èšèªãã䜿çšããã©ã€ãã©ãªçš)
CLIEvent 屿§ã䜿çšã㊠.NET ã€ãã³ããå ¬éãã
ãªããžã§ã¯ããš DelegateEvent ãåãåãç¹å®ã® .NET ããªã²ãŒãå (æ¢å®ã§ EventArgs åã®ã¿ã䜿çšãã Eventã§ã¯ãªã) ã䜿çšã㊠FSharpHandler ãæ§ç¯ããã€ãã³ããä»ã® .NET èšèªã«å¯ŸããŠäœ¿ãæ
£ããæ¹æ³ã§çºè¡ãããããã«ããŸãã
type MyBadType() =
let myEv = new Event<int>()
[<CLIEvent>]
member this.MyEvent = myEv.Publish
type MyEventArgs(x: int) =
inherit System.EventArgs()
member this.X = x
/// A type in a component designed for use from other .NET languages
type MyGoodType() =
let myEv = new DelegateEvent<EventHandler<MyEventArgs>>()
[<CLIEvent>]
member this.MyEvent = myEv.Publish
.NET ã¿ã¹ã¯ãè¿ãã¡ãœãããšããŠéåææäœãå ¬éãã
ã¿ã¹ã¯ã¯ãã¢ã¯ãã£ããªéåæèšç®ã衚ãããã« .NET ã§äœ¿çšãããŸãã äžè¬ã«ãã¿ã¹ã¯ã¯ F# Async<T> ãªããžã§ã¯ããããã³ã³ããžã·ã§ã³ãå°ãªããªããŸããããã¯ã"æ¢ã«å®è¡ãããŠãã" ã¿ã¹ã¯ã衚ãã䞊åã³ã³ããžã·ã§ã³ãå®è¡ããæ¹æ³ãããã£ã³ã»ã«ã·ã°ãã«ããã®ä»ã®ã³ã³ããã¹ã ãã©ã¡ãŒã¿ãŒã®äŒéãé ãæ¹æ³ã§ã¯äžç·ã«æ§æã§ããªãããã§ãã
ãã ããããã«é¢ããããTasks ãè¿ãã¡ãœããã¯ã.NET ã§ã®éåæããã°ã©ãã³ã°ã®æšæºçãªè¡šçŸã§ãã
/// A type in a component designed for use from other .NET languages
type MyType() =
let compute (x: int): Async<int> = async { ... }
member this.ComputeAsync(x) = compute x |> Async.StartAsTask
ãŸããæç€ºçãªãã£ã³ã»ã« ããŒã¯ã³ãåãå ¥ããããšãé »ç¹ã«å¿ èŠã«ãªããŸãã
/// A type in a component designed for use from other .NET languages
type MyType() =
let compute(x: int): Async<int> = async { ... }
member this.ComputeAsTask(x, cancellationToken) = Async.StartAsTask(compute x, cancellationToken)
F# 颿°åã®ä»£ããã« .NET ããªã²ãŒãåã䜿çšãã
ããã§ã¯ã"F# 颿°å" ã¯ãint -> intã®ãã㪠"ç¢å°" åãæå³ããŸãã
代ããã«ãæ¬¡ã®æäœãè¡ããŸãã
member this.Transform(f: int->int) =
...
ãããè¡ããŸãã
member this.Transform(f: Func<int,int>) =
...
F# 颿°ã®åã¯ãä»ã® .NET èšèªã« class FSharpFunc<T,U> ãšããŠè¡šç€ºãããããªã²ãŒãåãçè§£ããèšèªæ©èœãããŒã«ã«ã¯é©ããŠããªããªããŸãã .NET Framework 3.5 以éã察象ãšããäžäœã®ã¡ãœãããäœæããå Žåã.NET éçºè
ããããã® API ãäœæ©æŠã§äœ¿çšã§ããããã«ããããã«ãSystem.Func ããã³ System.Action ããªã²ãŒããçºè¡ã«é©ãã API ã§ãã (.NET Framework 2.0 ã察象ãšããå Žåãã·ã¹ãã å®çŸ©ããªã²ãŒãåã®æ¹ãå¶éãããŸããSystem.Converter<T,U> ãç¹å®ã®ããªã²ãŒãåã®å®çŸ©ãªã©ãå®çŸ©æžã¿ã®ããªã²ãŒãåã®äœ¿çšãæ€èšããŠãã ãã)ã
éã«ã.NET ããªã²ãŒãã¯ãF# åãã©ã€ãã©ãªã§ã¯èªç¶ã§ã¯ãããŸãã (F# ã«æ¥ç¶ããã©ã€ãã©ãªã®æ¬¡ã®ã»ã¯ã·ã§ã³ãåç §ããŠãã ãã)ã ãã®çµæãããã© .NET ã©ã€ãã©ãªã®äžäœã®ã¡ãœãããéçºããå Žåã®äžè¬çãªå®è£ æŠç¥ã¯ãF# 颿°åã䜿çšããŠãã¹ãŠã®å®è£ ãäœæããå®éã® F# å®è£ ã®äžã«ããªã²ãŒããèããã¡ãµãŒããšããŠäœ¿çšããŠãããªã㯠API ãäœæããããšã§ãã
F# ãªãã·ã§ã³å€ãè¿ã代ããã« TryGetValue ãã¿ãŒã³ã䜿çšããF# ãªãã·ã§ã³å€ãåŒæ°ãšããŠåãåããããã¡ãœããã®ãªãŒããŒããŒããåªå ããŸã
API ã® F# ãªãã·ã§ã³åã«å¯Ÿããäžè¬çãªäœ¿çšãã¿ãŒã³ã¯ãæšæºã® .NET èšèšææ³ã䜿çšããŠãããã© .NET API ã«å®è£ ããããšããå§ãããŸãã F# ãªãã·ã§ã³å€ãè¿ã代ããã«ããTryGetValueããã¿ãŒã³ã®ããã«ãbool åã®æ»ãå€ãš out ãã©ã¡ãŒã¿ãŒã䜿çšããããšãæ€èšããŠãã ããã ãŸããF# ãªãã·ã§ã³å€ããã©ã¡ãŒã¿ãŒãšããŠåãåã代ããã«ãã¡ãœããã®ãªãŒããŒããŒããŸãã¯çç¥å¯èœãªåŒæ°ã®äœ¿çšãæ€èšããŠãã ããã
member this.ReturnOption() = Some 3
member this.ReturnBoolAndOut(outVal: byref<int>) =
outVal <- 3
true
member this.ParamOption(x: int, y: int option) =
match y with
| Some y2 -> x + y2
| None -> x
member this.ParamOverload(x: int) = x
member this.ParamOverload(x: int, y: int) = x + y
ãã©ã¡ãŒã¿ãŒãšæ»ãå€ã® .NET ã³ã¬ã¯ã·ã§ã³ ã€ã³ã¿ãŒãã§ã€ã¹å IEnumerable<T> ããã³ IDictionary<KeyãValue> ã䜿çšãã
.NET é
å T[]ãF# å list<T>ãMap<Key,Value>ãããã³ Set<T>ããŸã Dictionary<Key,Value>ãªã©ã® .NET å
·è±¡ã³ã¬ã¯ã·ã§ã³åã®äœ¿çšã¯é¿ããŠãã ããã .NET ã©ã€ãã©ãªã®èšèšã¬ã€ãã©ã€ã³ã«ã¯ãIEnumerable<T>ãªã©ã®ããŸããŸãªã³ã¬ã¯ã·ã§ã³åã䜿çšããã¿ã€ãã³ã°ã«é¢ããé©åãªã¢ããã€ã¹ããããŸãã ããã©ãŒãã³ã¹äžã®çç±ãããç¶æ³ã«ãã£ãŠã¯é
å (T[]) ã®äœ¿çšã蚱容ãããå ŽåããããŸãã ç¹ã«ãseq<T> 㯠IEnumerable<T>ã® F# ãšã€ãªã¢ã¹ã«éããªããããå€ãã®å Žåãseq ã¯ããã© .NET API ã«é©ããåã§ããããšã«æ³šæããŠãã ããã
æšå¥šãããªã F# ã®äžèЧã®äŸ:
member this.PrintNames(names: string list) =
...
F# ã·ãŒã±ã³ã¹ã䜿çšããŸãã
member this.PrintNames(names: seq<string>) =
...
ãŒãåŒæ°ã¡ãœãããå®çŸ©ããã¡ãœããã®å¯äžã®å ¥ååãšããŠããŸã㯠void ãè¿ãã¡ãœãããå®çŸ©ããå¯äžã®æ»ãå€ã®åãšããŠãåäœåã䜿çšããŸãã
ãŠãããåã®ä»ã®äœ¿çšã¯é¿ããŠãã ããã ãããã¯é©åã§ãã
â member this.NoArguments() = 3
â member this.ReturnVoid(x: int) = ()
ããã¯æªãã§ã:
member this.WrongUnit( x: unit, z: int) = ((), ())
ããã© .NET API ã®å¢çã§ null å€ã確èªãã
F# ã®å®è£
ã³ãŒãã§ã¯ã倿Žã§ããªãèšèšãã¿ãŒã³ãš F# åã® null ãªãã©ã«ã®äœ¿çšã«é¢ããå¶éããããããnull å€ãå°ãªããªãåŸåããããŸãã ä»ã® .NET èšèªã§ã¯ãå€ãã®å Žåãå€ãšã㊠null ã䜿çšããé »åºŠãé«ããªããŸãã ãã®ãããããã© .NET API ãå
¬éããŠãã F# ã³ãŒãã§ã¯ãAPI ã®å¢çã§ãã©ã¡ãŒã¿ãŒã« null ããããã©ããã確èªãããããã®å€ã F# å®è£
ã³ãŒãã«æ·±ãå
¥ããªãããã«ããå¿
èŠããããŸãã
isNull ãã¿ãŒã³ã® null 颿°ãŸãã¯ãã¿ãŒã³ ãããã³ã°ã䜿çšã§ããŸãã
let checkNonNull argName (arg: obj) =
match arg with
| null -> nullArg argName
| _ -> ()
let checkNonNull' argName (arg: obj) =
if isNull arg then nullArg argName
else ()
F# 9 以éã§ã¯ãæ°ãã | nullæ§æ ãå©çšããŠãã³ã³ãã€ã©ãå¯èœãª null å€ãšãåŠçãå¿
èŠãªå Žæã瀺ãããšãã§ããŸãã
let checkNonNull argName (arg: obj | null) =
match arg with
| null -> nullArg argName
| _ -> ()
let checkNonNull' argName (arg: obj | null) =
if isNull arg then nullArg argName
else ()
F# 9 ã§ã¯ãå¯èœæ§ã®ãã null å€ãåŠçãããªãããšãæ€åºããããšãã³ã³ãã€ã©ã«ãã£ãŠèŠåãåºåãããŸãã
let printLineLength (s: string) =
printfn "%i" s.Length
let readLineFromStream (sr: System.IO.StreamReader) =
// `ReadLine` may return null here - when the stream is finished
let line = sr.ReadLine()
// nullness warning: The types 'string' and 'string | null'
// do not have equivalent nullability
printLineLength line
ãããã®èŠåã«ã¯ããããã³ã°ã§ F# ã® null ãã¿ãŒã³ã䜿çšããŠå¯ŸåŠããå¿ èŠããããŸãã
let printLineLength (s: string) =
printfn "%i" s.Length
let readLineFromStream (sr: System.IO.StreamReader) =
let line = sr.ReadLine()
match line with
| null -> ()
| s -> printLineLength s
æ»ãå€ãšããŠã¿ãã«ã䜿çšããªãããã«ãã
代ããã«ãéèšããŒã¿ãä¿æããååä»ãåãè¿ãããout ãã©ã¡ãŒã¿ãŒã䜿çšããŠè€æ°ã®å€ãè¿ããŸãã ã¿ãã«ãšæ§é äœã¿ãã«ã¯ .NET ã«ååšããŸã (æ§é äœã¿ãã«ã® C# èšèªãµããŒããå«ã)ãã»ãšãã©ã®å Žåã.NET éçºè ã«ãšã£ãŠçæ³çã§æåŸ ããã API ã¯æäŸãããŸããã
ãã©ã¡ãŒã¿ãŒã®ã«ãªãŒåã䜿çšããªã
代ããã«ãMethod(arg1,arg2,âŠ,argN).NET åŒã³åºãèŠåã䜿çšããŸãã
member this.TupledArguments(str, num) = String.replicate num str
ãã³ã: ä»»æã® .NET èšèªãã䜿çšããã©ã€ãã©ãªãèšèšããŠããå Žåã¯ãå®éã«å®éšçšã® C# ãš Visual Basic ããã°ã©ãã³ã°ãè¡ã£ãŠãã©ã€ãã©ãªããããã®èšèªãã "æ£ãããšæãã" ããã«ãã代ããã«ã¯ãããŸããã .NET Reflector ã Visual Studio ãªããžã§ã¯ã ãã©ãŠã¶ãŒãªã©ã®ããŒã«ã䜿çšããŠãã©ã€ãã©ãªãšãã®ããã¥ã¡ã³ããéçºè ã«æåŸ ã©ããã«è¡šç€ºãããããã«ããããšãã§ããŸãã
ä»é²
ä»ã® .NET èšèªã§äœ¿çšãã F# ã³ãŒããèšèšãããšã³ã ã㌠ãšã³ãã®äŸ
次ã®ã¯ã©ã¹ã«ã€ããŠèããŠã¿ãŸãããã
open System
type Point1(angle,radius) =
new() = Point1(angle=0.0, radius=0.0)
member x.Angle = angle
member x.Radius = radius
member x.Stretch(l) = Point1(angle=x.Angle, radius=x.Radius * l)
member x.Warp(f) = Point1(angle=f(x.Angle), radius=x.Radius)
static member Circle(n) =
[ for i in 1..n -> Point1(angle=2.0*Math.PI/float(n), radius=1.0) ]
ãã®ã¯ã©ã¹ã®æšè«ããã F# åã¯æ¬¡ã®ãšããã§ãã
type Point1 =
new : unit -> Point1
new : angle:double * radius:double -> Point1
static member Circle : n:int -> Point1 list
member Stretch : l:double -> Point1
member Warp : f:(double -> double) -> Point1
member Angle : double
member Radius : double
å¥ã® .NET èšèªã䜿çšããŠããã® F# åãããã°ã©ãã«ã©ã®ããã«è¡šç€ºãããããèŠãŠã¿ãŸãããã ããšãã°ãC# ã®ããããã® "ã·ã°ããã£" ã¯æ¬¡ã®ããã«ãªããŸãã
// C# signature for the unadjusted Point1 class
public class Point1
{
public Point1();
public Point1(double angle, double radius);
public static Microsoft.FSharp.Collections.List<Point1> Circle(int count);
public Point1 Stretch(double factor);
public Point1 Warp(Microsoft.FSharp.Core.FastFunc<double,double> transform);
public double Angle { get; }
public double Radius { get; }
}
ããã§ã¯ãF# ãã³ã³ã¹ãã©ã¯ããã©ã®ããã«è¡šããŠãããã«ã€ããŠæ³šæãã¹ãéèŠãªç¹ãããã€ããããŸãã äŸãã°ïŒ
åŒæ°åãªã©ã®ã¡ã¿ããŒã¿ã¯ä¿æãããŠããŸãã
2 ã€ã®åŒæ°ãåãåã F# ã¡ãœããã¯ã2 ã€ã®åŒæ°ãåãåã C# ã¡ãœããã«ãªããŸãã
颿°ãšãªã¹ãã¯ãF# ã©ã€ãã©ãªå ã®å¯Ÿå¿ããåãžã®åç §ã«ãªããŸãã
次ã®ã³ãŒãã¯ããããã®ããšãèæ ®ããããã«ãã®ã³ãŒãã調æŽããæ¹æ³ã瀺ããŠããŸãã
namespace SuperDuperFSharpLibrary.Types
type RadialPoint(angle:double, radius:double) =
/// Return a point at the origin
new() = RadialPoint(angle=0.0, radius=0.0)
/// The angle to the point, from the x-axis
member x.Angle = angle
/// The distance to the point, from the origin
member x.Radius = radius
/// Return a new point, with radius multiplied by the given factor
member x.Stretch(factor) =
RadialPoint(angle=angle, radius=radius * factor)
/// Return a new point, with angle transformed by the function
member x.Warp(transform:Func<_,_>) =
RadialPoint(angle=transform.Invoke angle, radius=radius)
/// Return a sequence of points describing an approximate circle using
/// the given count of points
static member Circle(count) =
seq { for i in 1..count ->
RadialPoint(angle=2.0*Math.PI/float(count), radius=1.0) }
æšå®ãããã³ãŒãã® F# åã¯æ¬¡ã®ãšããã§ãã
type RadialPoint =
new : unit -> RadialPoint
new : angle:double * radius:double -> RadialPoint
static member Circle : count:int -> seq<RadialPoint>
member Stretch : factor:double -> RadialPoint
member Warp : transform:System.Func<double,double> -> RadialPoint
member Angle : double
member Radius : double
C# ã·ã°ããã£ã¯æ¬¡ã®ããã«ãªããŸãã
public class RadialPoint
{
public RadialPoint();
public RadialPoint(double angle, double radius);
public static System.Collections.Generic.IEnumerable<RadialPoint> Circle(int count);
public RadialPoint Stretch(double factor);
public RadialPoint Warp(System.Func<double,double> transform);
public double Angle { get; }
public double Radius { get; }
}
ããã© .NET ã©ã€ãã©ãªã®äžéšãšããŠäœ¿çšããããã«ãã®åãæºåããããã«è¡ãããä¿®æ£ã¯æ¬¡ã®ãšããã§ãã
ããã€ãã®ååã調æŽããŸãã:
Point1ãnãlãããã³fã¯ããããRadialPointãcountãfactorãããã³transformã«ãªããŸãããseq<RadialPoint>ã䜿ã£ããªã¹ãæ§ç¯ãRadialPoint listã䜿ã£ãã·ãŒã±ã³ã¹æ§ç¯ã«å€æŽããããšã§ã[ ... ]ã§ã¯ãªãIEnumerable<RadialPoint>ã®æ»ãå€ã®åãçšããŸãããF# 颿°åã®ä»£ããã«
System.Func.NET ããªã²ãŒãåã䜿çšããŸããã
C# ã³ãŒãã§ã®äœ¿çšãã¯ããã«äœ¿ãããããªããŸãã