or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-lenses.mdindex.mdlens-constructors.mdoptics.mdutility-types.md

optics.mddocs/

0

# Optics System

1

2

Low-level optics system providing the mathematical foundation for lens operations. The optics system implements different types of optics (Lens, Prism, Traversal, Isomorphism, etc.) that can be composed to create complex data access patterns.

3

4

## Capabilities

5

6

### Base Optics Interface

7

8

Core interfaces and base classes that define the optics system.

9

10

```python { .api }

11

class LensLike:

12

"""Base interface for all optic types."""

13

def kind(self): ...

14

def compose(self, other): ...

15

def view(self, state): ...

16

def over(self, state, func): ...

17

def set(self, state, value): ...

18

def to_list_of(self, state): ...

19

20

class TrivialIso:

21

"""Identity isomorphism - does nothing."""

22

pass

23

24

class ComposedLens:

25

"""Composed optic combining two optics."""

26

def __init__(self, lens1, lens2): ...

27

28

class Equality:

29

"""Equality-based optic."""

30

pass

31

32

class TupleOptic:

33

"""Combines multiple optic focuses into a tuple."""

34

def __init__(self, *optics): ...

35

```

36

37

### Optic Types by Capability

38

39

Different optic types providing various levels of access capability.

40

41

```python { .api }

42

class Fold:

43

"""Read-only access to multiple foci."""

44

def __init__(self, func: Callable[[A], Iterable[X]]): ...

45

46

class Getter:

47

"""Read-only access to single focus."""

48

def __init__(self, getter: Callable[[A], X]): ...

49

50

class Setter:

51

"""Write-only access to foci."""

52

pass

53

54

class Review:

55

"""Write-only optic for constructing values."""

56

pass

57

58

class Traversal:

59

"""Read-write access to multiple foci."""

60

def __init__(self, folder: Callable[[A], Iterable[X]],

61

builder: Callable[[A, Iterable[Y]], B]): ...

62

63

class Lens:

64

"""Read-write access to single focus."""

65

def __init__(self, getter: Callable[[A], X],

66

setter: Callable[[A, Y], B]): ...

67

68

class Prism:

69

"""Optional read-write access (zero or one focus)."""

70

def __init__(self, unpack: Callable[[A], Just[X]],

71

pack: Callable[[Y], B]): ...

72

73

class Isomorphism:

74

"""Bidirectional conversion between types."""

75

def __init__(self, forwards: Callable[[A], X],

76

backwards: Callable[[Y], B]): ...

77

def re(self): ... # Reverse the isomorphism

78

```

79

80

### Concrete Fold Implementations

81

82

Specific fold implementations for read-only traversal.

83

84

```python { .api }

85

class IterableFold:

86

"""Fold over any iterable object."""

87

pass

88

```

89

90

#### Usage Examples

91

92

```python

93

from lenses.optics import IterableFold

94

from lenses import lens

95

96

# Direct optic usage (advanced)

97

fold = IterableFold()

98

data = [1, 2, 3, 4, 5]

99

values = fold.to_list_of(data) # [1, 2, 3, 4, 5]

100

101

# More commonly used through lens interface

102

lens.Iter().collect()(data) # [1, 2, 3, 4, 5]

103

```

104

105

### Concrete Isomorphism Implementations

106

107

Isomorphisms for converting between different data representations.

108

109

```python { .api }

110

class DecodeIso:

111

"""String/bytes encoding conversion isomorphism."""

112

def __init__(self, encoding: str = "utf-8", errors: str = "strict"): ...

113

114

class JsonIso:

115

"""JSON string parsing isomorphism."""

116

pass

117

118

class NormalisingIso:

119

"""Value normalization isomorphism."""

120

def __init__(self, setter: Callable[[A], X]): ...

121

122

class ErrorIso:

123

"""Exception-raising isomorphism for debugging."""

124

def __init__(self, exception: Exception, message: Optional[str] = None): ...

125

```

126

127

#### Usage Examples

128

129

```python

130

from lenses.optics import JsonIso, DecodeIso

131

from lenses import lens

132

133

# JSON isomorphism

134

json_iso = JsonIso()

135

json_data = '{"name": "Alice", "age": 30}'

136

parsed = json_iso.view(json_data) # {"name": "Alice", "age": 30}

137

138

# Through lens interface (more common)

139

name = lens.Json()["name"].get()(json_data) # "Alice"

140

141

# Decode isomorphism

142

decode_iso = DecodeIso("utf-8")

143

byte_data = b"hello"

144

text = decode_iso.view(byte_data) # "hello"

145

```

146

147

### Concrete Prism Implementations

148

149

Prisms for optional or conditional access patterns.

150

151

```python { .api }

152

class FilteringPrism:

153

"""Prism that filters by predicate."""

154

def __init__(self, predicate: Callable[[A], bool]): ...

155

156

class InstancePrism:

157

"""Prism that filters by type."""

158

def __init__(self, type_: Type): ...

159

160

class JustPrism:

161

"""Prism for Maybe Just values."""

162

pass

163

```

164

165

#### Usage Examples

166

167

```python

168

from lenses.optics import FilteringPrism, InstancePrism

169

from lenses import lens

170

171

# Filtering prism

172

positive_prism = FilteringPrism(lambda x: x > 0)

173

data = [-1, 2, -3, 4]

174

positive_values = [positive_prism.to_list_of([x]) for x in data] # [[], [2], [], [4]]

175

176

# Through lens interface (more common)

177

positive = lens.Each().Filter(lambda x: x > 0).collect()(data) # [2, 4]

178

179

# Instance prism for type filtering

180

str_prism = InstancePrism(str)

181

mixed = [1, "hello", 2.5, "world"]

182

strings = lens.Each().Instance(str).collect()(mixed) # ["hello", "world"]

183

```

184

185

### Concrete Setter Implementations

186

187

Setters for write-only operations.

188

189

```python { .api }

190

class ForkedSetter:

191

"""Parallel composition of multiple setters."""

192

def __init__(self, *setters): ...

193

```

194

195

#### Usage Examples

196

197

```python

198

from lenses.optics import ForkedSetter, GetitemLens

199

from lenses import lens

200

201

# Forked setter for parallel updates

202

fork = ForkedSetter(GetitemLens(0), GetitemLens(2))

203

data = [1, 2, 3, 4, 5]

204

updated = fork.set(data, 99) # [99, 2, 99, 4, 5]

205

206

# Through lens interface (more common)

207

fork_lens = lens.Fork(lens[0], lens[2])

208

result = fork_lens.set(99)(data) # [99, 2, 99, 4, 5]

209

```

210

211

### Concrete Traversal Implementations

212

213

Traversals for read-write access to multiple foci.

214

215

```python { .api }

216

class EachTraversal:

217

"""Traverse all items in a collection."""

218

pass

219

220

class ItemsTraversal:

221

"""Traverse dictionary items as (key, value) pairs."""

222

pass

223

224

class RecurTraversal:

225

"""Recursively traverse objects of a specific type."""

226

def __init__(self, cls): ...

227

228

class RegexTraversal:

229

"""Traverse string parts matching a regex pattern."""

230

def __init__(self, pattern: Pattern, flags: int = 0): ...

231

232

class GetZoomAttrTraversal:

233

"""Traverse attribute, zooming if it's a lens."""

234

def __init__(self, name: str): ...

235

236

class ZoomAttrTraversal:

237

"""Traverse lens attribute."""

238

def __init__(self, name: str): ...

239

240

class ZoomTraversal:

241

"""Follow bound lens objects."""

242

pass

243

```

244

245

#### Usage Examples

246

247

```python

248

from lenses.optics import EachTraversal, RecurTraversal

249

from lenses import lens

250

251

# Each traversal

252

each = EachTraversal()

253

data = [1, 2, 3]

254

values = each.to_list_of(data) # [1, 2, 3]

255

doubled = each.over(data, lambda x: x * 2) # [2, 4, 6]

256

257

# Recursive traversal

258

recur = RecurTraversal(int)

259

nested = [1, [2, 3], [[4]], 5]

260

all_ints = recur.to_list_of(nested) # [1, 2, 3, 4, 5]

261

262

# Through lens interface (more common)

263

all_ints_lens = lens.Recur(int).collect()(nested) # [1, 2, 3, 4, 5]

264

```

265

266

### Concrete Lens Implementations

267

268

True lenses providing read-write access to single foci.

269

270

```python { .api }

271

class GetattrLens:

272

"""Lens for object attributes."""

273

def __init__(self, name: str): ...

274

275

class GetitemLens:

276

"""Lens for container items."""

277

def __init__(self, key: Any): ...

278

279

class GetitemOrElseLens:

280

"""Lens for container items with default values."""

281

def __init__(self, key: Any, default: Optional[Y] = None): ...

282

283

class ContainsLens:

284

"""Lens for collection containment as boolean."""

285

def __init__(self, item: A): ...

286

287

class ItemLens:

288

"""Lens for dictionary items as (key, value) pairs."""

289

def __init__(self, key: Any): ...

290

291

class ItemByValueLens:

292

"""Lens for dictionary items by value."""

293

def __init__(self, value: Any): ...

294

295

class PartsLens:

296

"""Converts fold/traversal to lens by collecting parts."""

297

def __init__(self, optic): ...

298

```

299

300

#### Usage Examples

301

302

```python

303

from lenses.optics import GetitemLens, GetattrLens, ContainsLens

304

from lenses import lens

305

306

# Getitem lens

307

item_lens = GetitemLens(0)

308

data = [10, 20, 30]

309

first = item_lens.view(data) # 10

310

updated = item_lens.set(data, 99) # [99, 20, 30]

311

312

# Getattr lens

313

from collections import namedtuple

314

Person = namedtuple('Person', 'name age')

315

person = Person("Alice", 30)

316

name_lens = GetattrLens('name')

317

name = name_lens.view(person) # "Alice"

318

319

# Contains lens

320

contains_lens = ContainsLens(2)

321

data = [1, 2, 3]

322

has_two = contains_lens.view(data) # True

323

without_two = contains_lens.set(data, False) # [1, 3]

324

325

# Through lens interface (more common)

326

first_item = lens[0].get()(data) # 10

327

person_name = lens.GetAttr('name').get()(person) # "Alice"

328

```

329

330

### Optic Composition

331

332

How optics compose to create complex access patterns.

333

334

```python { .api }

335

def compose_optics(optic1, optic2):

336

"""Compose two optics into a single optic."""

337

return ComposedLens(optic1, optic2)

338

```

339

340

#### Composition Examples

341

342

```python

343

from lenses.optics import GetitemLens, EachTraversal

344

from lenses import lens

345

346

# Manual composition (advanced usage)

347

first_item = GetitemLens(0)

348

each_item = EachTraversal()

349

composed = first_item.compose(each_item)

350

351

# Through lens interface (recommended)

352

data = [[1, 2], [3, 4], [5, 6]]

353

first_each = lens[0].Each().collect()(data) # [1, 2]

354

355

# Complex compositions

356

nested_access = (lens["users"]

357

.Each()

358

.Filter(lambda u: u.get("active", False))

359

["profile"]

360

["name"])

361

```