Skip to content

Commit c0cda06

Browse files
authored
Merge pull request #1327 from lean-ja/Seasawher/issue1318
`ToString` の例が不適切
2 parents 750de2e + 363e8b7 commit c0cda06

File tree

1 file changed

+42
-44
lines changed

1 file changed

+42
-44
lines changed
Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,62 @@
11
/-
22
# ToString
3-
`ToString` は、文字列への変換を行う型クラスです
3+
`ToString` は、文字列 `String` への変換方法を提供する型クラスです。`ToString` のインスタンスになっている型の項は、`toString` 関数で文字列に変換することができます
44
-/
5-
namespace ToString --#
5+
import Lean --#
66

7-
structure Point (α : Type) where
8-
x : α
9-
y : α
7+
/-- 標準ライブラリの `List` を真似て作った自前のリスト -/
8+
inductive MyList (α : Type) where
9+
| nil : MyList α
10+
| cons (hd : α) (tl : MyList α) : MyList α
1011

11-
def origin : Point Int := ⟨0, 0
12+
namespace MyList
1213

13-
-- 文字列補完により文字列に変換しようとしても、
14-
-- 最初はどう変換したらいいのかわからないのでエラーになる
15-
/--
16-
error: failed to synthesize
17-
ToString (Point Int)
18-
Additional diagnostic information may be available using the `set_option diagnostics true` command.
19-
-/
20-
#guard_msgs (error) in #check s!"{origin}"
21-
22-
/-- `ToString` のインスタンスを登録する -/
23-
instance : ToString (Point Int) where
24-
toString p := s!"Point: ({p.x}, {p.y})"
14+
variable {α : Type}
2515

26-
-- これで文字列に変換できる
27-
/-- info: "Point: (0, 0)" -/
28-
#guard_msgs in #eval s!"{origin}"
16+
/-- リストをリストらしく `"[a₁, a₂, ..., aₙ]"` という文字列に変換する
17+
**注意**: `ToString.toString` と紛らわしいことがあるので `protected` で修飾している
18+
-/
19+
protected def toString [ToString α] : MyList α → String
20+
| nil => "[]"
21+
| ls@(cons _hd _tail) =>
22+
"[" ++ helper ls ++ "]"
23+
where
24+
/-- 外側の括弧抜きでリストの中身を `,` でつないで表示する -/
25+
helper : MyList α → String
26+
| nil => ""
27+
| cons hd .nil => toString hd
28+
| cons hd tail => toString hd ++ ", " ++ helper tail
2929

30-
/- ## Repr と ToString
30+
instance [ToString α] : ToString (MyList α) where
31+
toString := MyList.toString
3132

32-
[`Repr`](./Repr.md) のインスタンスはないが、`ToString` のインスタンスはあるという状態で `#eval` しようとすると、`Repr` の代わりに `ToString` のインスタンスが使用されます。`Repr` のインスタンスを与えればそちらが優先して使用されます。-/
33+
-- `toString` が正しく動作しているかテスト
34+
#guard (toString <| MyList.cons 1 (MyList.nil)) = "[1]"
35+
#guard (toString <| MyList.cons 1 (MyList.cons 2 (MyList.nil))) = "[1, 2]"
3336

34-
/-- info: Point: (0, 0) -/
35-
#guard_msgs in #eval origin
37+
end MyList
3638

37-
-- `Repr` のインスタンスを自動生成して登録する
38-
-- 以降は、`#eval` 時には `Repr` のインスタンスが使用される
39-
deriving instance Repr for Point
4039

41-
/-- info: { x := 0, y := 0 } -/
42-
#guard_msgs in #eval origin
4340

44-
/- 逆に、`Repr` のインスタンスはあるが、`ToString` のインスタンスがないとき、`ToString` の代わりに `Repr` が呼び出されることはありません。エラーになります。-/
41+
/- ## ReprToString の違い
4542
46-
structure Person where
47-
name : String
48-
age : Nat
49-
deriving Repr
43+
[`Repr`](#{root}/TypeClass/Repr.md) と [`ToString`](#{root}/TypeClass/ToString.md) はどちらも項の表示に関わる型クラスですが、使い分けのルールが存在しており、それは `Repr` のドキュメントコメントに書かれています。
44+
-/
5045

51-
def david := Person.mk "David" 42
46+
open Lean Elab Command in
5247

53-
-- #eval はできる
54-
#eval david
48+
/-- ドキュメントコメントを取得して表示するコマンド -/
49+
elab "#doc " x:ident : command => do
50+
let name ← liftCoreM do realizeGlobalConstNoOverload x
51+
if let some s ← findDocString? (← getEnv) name then
52+
logInfo m!"{s}"
5553

56-
-- `ToString` のインスタンスがないのでエラーになる
5754
/--
58-
error: failed to synthesize
59-
ToString Person
60-
Additional diagnostic information may be available using the `set_option diagnostics true` command.
55+
info: A typeclass that specifies the standard way of turning values of some type into `Format`.
56+
57+
When rendered this `Format` should be as close as possible to something that can be parsed as the
58+
input value.
6159
-/
62-
#guard_msgs (error) in #check s!"{david}"
60+
#guard_msgs in #doc Repr
6361

64-
end ToString --#
62+
/- `Repr` の出力は Lean のコードとしてパース可能なものに可能な限り近くなければならない、つまり Lean のコードとして実行可能であることが期待されます。一方で、`ToString` は単なる `String` への変換であってそのような制約はありません。 -/

0 commit comments

Comments
 (0)