-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathDependsOnNoncomputable.lean
More file actions
122 lines (108 loc) · 4.27 KB
/
Copy pathDependsOnNoncomputable.lean
File metadata and controls
122 lines (108 loc) · 4.27 KB
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/-
Copyright (c) 2025 Lean FRO LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Joseph Rotella, Rob Simmons
-/
import VersoManual
import Manual.Meta.ErrorExplanation
open Lean
open Verso.Genre Manual InlineLean
#doc (Manual) "About: `dependsOnNoncomputable`" =>
%%%
shortTitle := "dependsOnNoncomputable"
%%%
{errorExplanationHeader lean.dependsOnNoncomputable}
This error indicates that the specified definition depends on one or more definitions that do not
contain executable code and is therefore required to be marked as {keyword}`noncomputable`. Such
definitions can be type-checked but do not contain code that can be executed by Lean.
If you intended for the definition named in the error message to be noncomputable, marking it as
{keyword}`noncomputable` will resolve this error. If you did not, inspect the noncomputable
definitions on which it depends: they may be noncomputable because they failed to compile, are
{keyword}`axiom`s, or were themselves marked as {keyword}`noncomputable`. Making all of your
definition's noncomputable dependencies computable will also resolve this error. See the manual
section on {ref "declaration-modifiers"}[Modifiers] for more information about noncomputable
definitions.
# Examples
:::errorExample "Necessarily Noncomputable Function Not Appropriately Marked"
```broken
axiom transform : Nat → Nat
def transformIfZero : Nat → Nat
| 0 => transform 0
| n => n
```
```output
`transform` not supported by code generator; consider marking definition as `noncomputable`
```
```fixed
axiom transform : Nat → Nat
noncomputable def transformIfZero : Nat → Nat
| 0 => transform 0
| n => n
```
In this example, `transformIfZero` depends on the axiom `transform`. Because `transform` is an
axiom, it does not contain any executable code; although the value `transform 0` has type `Nat`,
there is no way to compute its value. Thus, `transformIfZero` must be marked `noncomputable` because
its execution would depend on this axiom.
:::
:::errorExample "Noncomputable Dependency Can Be Made Computable"
```broken
noncomputable def getOrDefault [Nonempty α] : Option α → α
| some x => x
| none => Classical.ofNonempty
def endsOrDefault (ns : List Nat) : Nat × Nat :=
let head := getOrDefault ns.head?
let tail := getOrDefault ns.getLast?
(head, tail)
```
```output
failed to compile definition, consider marking it as 'noncomputable' because it depends on 'getOrDefault', which is 'noncomputable'
```
```fixed
def getOrDefault [Inhabited α] : Option α → α
| some x => x
| none => default
def endsOrDefault (ns : List Nat) : Nat × Nat :=
let head := getOrDefault ns.head?
let tail := getOrDefault ns.getLast?
(head, tail)
```
The original definition of `getOrDefault` is noncomputable due to its use of `Classical.choice`.
Unlike in the preceding example, however, it is possible to implement a similar but computable
version of `getOrDefault` (using the {name}`Inhabited` type class), allowing `endsOrDefault` to be
computable. (The differences between {name}`Inhabited` and {name}`Nonempty` are described in the documentation
of inhabited types in the manual section on {ref "basic-classes"}[Basic Classes].)
:::
:::errorExample "Noncomputable Instance in Namespace"
```broken
open Classical in
/--
Returns `y` if it is in the image of `f`,
or an element of the image of `f` otherwise.
-/
def fromImage (f : Nat → Nat) (y : Nat) :=
if ∃ x, f x = y then
y
else
f 0
```
```output
failed to compile definition, consider marking it as 'noncomputable' because it depends on 'propDecidable', which is 'noncomputable'
```
```fixed
open Classical in
/--
Returns `y` if it is in the image of `f`,
or an element of the image of `f` otherwise.
-/
noncomputable def fromImage (f : Nat → Nat) (y : Nat) :=
if ∃ x, f x = y then
y
else
f 0
```
The {name}`Classical` namespace contains {name}`Decidable` instances that are not computable. These are a common
source of noncomputable dependencies that do not explicitly appear in the source code of a
definition. In the above example, for instance, a {name}`Decidable` instance for the proposition
{lean}`∃ x, f x = y` is synthesized using a {name}`Classical` decidability instance; therefore, {name}`fromImage` must
be marked {keyword}`noncomputable`.
:::