Closed12
F# の学習ログ
F# をやってみたいと思った。
インストール
省略
hello world
を読んでいく。
dotnet new console -lang="F#"
// Learn more about F# at http://docs.microsoft.com/dotnet/fsharp
open System
// Define a function to construct a message to print
let from whom = sprintf "from %s" whom
[<EntryPoint>]
let main argv =
let message = from "F#" // Call the function
printfn "Hello world %s" message
0
dotnet add package FSharp.Scanf
するとパッケージが入る。パッケージマネージャはnugetらしい。
open FSharp.Scanf
printfn "input a number"
try
let ans = scanfn "%i"
if ans = 42 then
printfn "the ultimate answer"
else
printfn "recieved %i" ans
with _ -> printfn "not a number... :("
-
open
というのがimportに相当するっぽい。正確にはFSharp.Scanf
名前空間にある物体を展開する感じか。 -
"%i"
でフォーマットなのはわかる。興味深いのは%i
にシンタックスハイライトが効いているところ、関数適用に括弧がいらないところ。- 関数適用がスペースでできる言語でフォーマットするのが新鮮
-
scanfn
はライブラリの関数みたいだけど、それに対してフォーマット文字列にハイライトが効いてるのが気になる-
scanfn
はPrintfFormat<'a,'b,'c,'d, ^e>
、printfn
はTextWriterFormat<'T>
型を受け取っている。特定のクラスを継承した文字列を特別に扱っているのかもしれない。そしてそのカスタマイズの幅は明らかに広そう
-
-
[<EntryPoint>]
という属性をつけるとエントリーポイントになるらしい。コマンドライン引数を受け取れる。 - 関数定義はHaskellぽく名前から続けて引数を書くやつ。
を読んでいこうかな。
年相応に英語の表現もメモしておく。
- conciseness…簡潔さ
- be cluttered up with…~でとっ散らかった
- compared with <名詞>, …<>と比較して、
パイプライン演算子とかListを範囲指定で作るやつとかがある。そして地味にフォーマットで部分適用ができるのがすごい。
[ 1 .. 100 ] |> List.sum |> printfn "sum=%d"
型定義とか。けっこう軽率にADTが作れる。
type Person = { First: string; Last: string }
type Employee =
| Worker of Person
| Manager of Employee list
let asak = { Last = "Agoshi"; First = "Sakina" }
let schi = { Last = "Chiaki"; First = "Soen" }
let worker = Worker asak
let employee = Manager [ Worker schi; worker ]
OCamlをやって戻ってきた。
をやっていく。パーサコンビネータを作る。ただし2週目なのであまり細かくは書かない。
1文字をパースするやつ。
let pChar char str =
if System.String.IsNullOrEmpty(str) then
let msg = "No more input"
Error msg
else
let first = str.[0]
if first = char then
let remaining = str.[1..]
Ok(char, remaining)
else
let msg = sprintf "Expected %c, got %c" char first
Error msg
[<EntryPoint>]
let main _ =
let pA = pChar 'A'
printfn "%A" (pA "ABC")
printfn "%A" (pA "ZBC")
0
2つのパーサを試すやつ。
let either parser1 parser2 =
let innerFn input =
match run parser1 input with
| Ok _ as r -> r
| Error _ -> run parser2 input
Parser innerFn
let (<|>) = either
[<EntryPoint>]
let main _ =
let pA = pChar 'A'
let pAOrB = pChar 'A' <|> pChar 'B'
printfn "%A" (run pAOrB "ABC")
printfn "%A" (run pAOrB "BBC")
printfn "%A" (run pAOrB "ZBC")
0
let choice parsers = List.reduce (<|>) parsers
[<EntryPoint>]
let main _ =
let parseAOrBOrC =
[ 'A'; 'B'; 'C' ]
|> List.map pChar
|> choice
printfn "%A" (run parseAOrBOrC "ABC")
printfn "%A" (run parseAOrBOrC "BBC")
printfn "%A" (run parseAOrBOrC "CBC")
printfn "%A" (run parseAOrBOrC "ZBC")
0
このスクラップは2022/02/07にクローズされました