F

.envファイルを読み込みたい

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
open System
open System.IO

let parseLine(line : string) =
  Console.WriteLine (sprintf "Parsing: %s" line)
  match line.Split('=', StringSplitOptions.RemoveEmptyEntries) with
  | args when args.Length = 2 -> Environment.SetEnvironmentVariable(args.[0], args.[1])
  | _ -> ()

let load() =
  lazy (
    Console.WriteLine "Trying to load .env file..."
    let currentDir = Directory.GetCurrentDirectory()
    let pDir = Directory.GetParent(currentDir).ToString() // 都合によって親ディレクトリの.envを読んでいるが必要なければ削除
    let filePath = Path.Combine(pDir, ".env") // 親ディレクトリの.envを読んでいるので同じディレクトリにあるなら適切に書き換える
    filePath
    |> File.Exists
    |> function
      | false -> Console.WriteLine "No .env file found."
      | true  -> filePath |> File.ReadAllLines |> Seq.iter parseLine
  )
let init = load().Value

// 環境変数から読み込む部分
let apiRootUrl = Environment.GetEnvironmentVariable "NEXT_PUBLIC_API_ROOT_URL"

bottom

1
2
3
4
let undefined<'T> : 'T = failwith "Not implemented yet"

let stub1 (x : int) : float = undefined
let stub2 (x : 'T) : 'T = undefined
1
let undefined<'T> : 'T = raise (NotImplementedException())

fsx実行: 競プロ用実行

1
2
dotnet fsi hoge.fsx
dotnet fsi hoge.fsx < input.txt

fsxで他のfsxを読み込む

1
2
#load "Script1.fsx"
open Script1

Fable

メモ

1
2
dotnet new --install Fable.Template
dotnet new fable

Json

1
2
3
4
5
6
7
8
9
open System.Text.Json
open System.Text.Json.Serialization
open System.Text.Encodings.Web
open System.Text.Unicode

let mutable options = JsonSerializerOptions()
options.Encoder <- JavaScriptEncoder.Create(UnicodeRanges.All)
let jsonString = JsonSerializer.Serialize(items, options)
System.IO.File.WriteAllText(outputJsonFileName, jsonString, System.Text.Encoding.UTF8)

Stack overflow

AtCoderの木DPで, Pythonコードに沿って実装してみたらStack overflowしたのでその対処の記録.

Stringにはreverseがない(?)ので代替策を見つけた

どなたか有識者の方, いい感じのメソッドがあれば教えてほしい. 今回はProject Euler Problem 4の回文数の問題を解いているときに出くわした. どうもStringにはreverseメソッドがないらしい. 検索した結果, 今回はこのページのコピペとして次のコードを採用した.

1
2
let reverse (s : string) = s |> Seq.toArray |> Array.rev |> System.String
s |> Seq.rev |> System.String.Concat

あと最近F#のリファレンスがGitHubにうつったようだ. そのリンクも改めて貼っておこう.

GitHubのAlgorithmsAndDataStructureByFSharpにアルゴリズム系のコードと共にF#の「ライブラリ」という名の自分用コードサンプル集を作ってある. 具体的にはLibraryディレクトリがそう. そのうち競プロ用にいろいろ調べたことを改めてLibraryにまとめ直したい. 何はともあれ,

F#, とにかく情報がないので地道に貯めていく.

型プロバイダー FSharp.Dataの型プロバイダーには定数しか渡せない

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#r "nuget: FSharp.Data"
open FSharp.Data
open FSharp.Data.HttpRequestHeaders

let toJson = fun (x: HttpResponse) ->
  match x.Body with
  | Text t -> t
  | _ -> failwith "bytes"

/// http://localhost
type Root = FSharp.Data.JsonProvider<"http://localhost">
Http.Request("http://localhost", httpMethod = "GET") |> toJson |> fun t -> Root.Parse(t)

型プロバイダー 実行時のディレクトリ指定

1
2
3
4
#r "nuget: FSharp.Data"
open FSharp.Data

type Comments = JsonProvider<"sampleResponse.json", ResolutionFolder=__SOURCE_DIRECTORY__>;;

関数に型をつける

ふつうの方法

1
let f (i:int) (j:int): int = i * j

ラムダを使う方法

1
2
let f: int -> int -> int =
  fun i j -> i * j

空シーケンスの判定, 特にmatch

1
2
3
4
let rec dropWhile p xs =
  match xs with
    | s when Seq.isEmpty s -> Seq.empty
    | _ -> if p (Seq.head) then dropWhile p (Seq.tail xs) else (Seq.tail xs)

処理時間測定

1
2
3
4
5
6
open System.Diagnostics
let sw = System.Diagnostics.Stopwatch()
sw.Start()
// 処理
sw.Stop()
stdout.WriteLine(sw.Elapsed)

遅延リストはとりあえずSeq

1
Seq.initInfinite (fun i -> 2 * i + 1)

ファイルの読み書き

1
2
let fileName = "1.tmp.txt"
System.IO.File.WriteAllText(fileName, someString, System.Text.Encoding.Default)

複数行の文字列, ヒアドキュメント

C#と同じように書ける模様. 特に三重引用符または「@+クオート」で書ける. ついでに逐次的リテラル文字列の概念があり, 後者の「@+クォート」形式がそれ. 例を引用しておく.

1
2
".¥¥hoge¥¥hoge¥¥hoge.txt" // ふつうの文字列
@".¥hoge¥hoge¥hoge.txt"   // 逐次的リテラル文字列

プロジェクト作成

VSCodeを前提にする.

setup.txt

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
dotnet new sln -o MySolution
cd MySolution
mkdir src
dotnet new console -lang F# -o src/MyProject
dotnet sln add src/MyProject/MyProject.fsproj
mkdir tests
dotnet new xunit -lang F# -o tests/MyProjectTests
dotnet sln add tests/MyProjectTests/MyProjectTests.fsproj
cd tests/MyProjectTests
dotnet add reference ../../src/MyProject/MyProject.fsproj
dotnet add package FsUnit
dotnet add package FsUnit.XUnit
dotnet build
dotnet test