or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

utility-types.mddocs/

0

# Utility Types

1

2

Supporting types and systems that enhance the lens library's functionality, including Maybe monad for optional values, type class system for functional programming patterns, and hooks system for extending support to custom data types.

3

4

## Capabilities

5

6

### Maybe Type System

7

8

Optional value handling inspired by functional programming, providing safe operations on values that may or may not exist.

9

10

```python { .api }

11

class Just:

12

"""Container for a value that exists."""

13

def __init__(self, item: A) -> None: ...

14

15

def map(self, fn: Callable[[A], B]) -> Just[B]:

16

"""Apply function to contained value."""

17

18

def maybe(self, guard: B) -> Union[A, B]:

19

"""Extract value or return guard if Nothing."""

20

21

def unwrap(self) -> A:

22

"""Extract value (raises if Nothing)."""

23

24

def is_nothing(self) -> bool:

25

"""Check if this is Nothing."""

26

27

def __add__(self, other: Just[A]) -> Just[A]: ...

28

def __eq__(self, other: object) -> bool: ...

29

def __iter__(self) -> Iterator[A]: ...

30

31

class Nothing(Just):

32

"""Empty container representing no value."""

33

def __init__(self) -> None: ...

34

35

def map(self, fn: Callable[[A], B]) -> Just[B]:

36

"""Always returns Nothing."""

37

38

def maybe(self, guard: B) -> Union[A, B]:

39

"""Always returns guard."""

40

41

def unwrap(self) -> A:

42

"""Always raises ValueError."""

43

44

def is_nothing(self) -> bool:

45

"""Always returns True."""

46

```

47

48

#### Usage Examples

49

50

```python

51

from lenses.maybe import Just, Nothing

52

53

# Creating Maybe values

54

some_value = Just(42)

55

no_value = Nothing()

56

57

# Safe operations

58

result1 = some_value.map(lambda x: x * 2) # Just(84)

59

result2 = no_value.map(lambda x: x * 2) # Nothing()

60

61

# Extracting values safely

62

value1 = some_value.maybe(0) # 42

63

value2 = no_value.maybe(0) # 0 (guard value)

64

65

# Checking for values

66

print(some_value.is_nothing()) # False

67

print(no_value.is_nothing()) # True

68

69

# Unwrapping (dangerous)

70

actual_value = some_value.unwrap() # 42

71

# no_value.unwrap() # Raises ValueError

72

73

# Used with lenses

74

from lenses import lens

75

data = [Just(1), Nothing(), Just(3), Nothing(), Just(5)]

76

values = lens.Each().Just().collect()(data) # [1, 3, 5]

77

```

78

79

### Type Class System

80

81

Functional programming type classes providing generic operations for different data types.

82

83

```python { .api }

84

# Monoid operations

85

def mempty(monoid: Any) -> Any:

86

"""Get the empty/identity value for a monoid type."""

87

88

def mappend(monoid: Any, other: Any) -> Any:

89

"""Combine two monoid values."""

90

91

# Functor operations

92

def fmap(functor: Any, func: Callable[[Any], Any]) -> Any:

93

"""Apply function inside a functor context."""

94

95

# Applicative operations

96

def pure(applicative: Any, item: B) -> Any:

97

"""Wrap a value in an applicative context."""

98

99

def apply(applicative: Any, func: Any) -> Any:

100

"""Apply wrapped function to wrapped value."""

101

```

102

103

#### Built-in Type Support

104

105

```python { .api }

106

# Monoid instances for built-in types

107

mempty(0) # -> 0 (int)

108

mempty("") # -> "" (str)

109

mempty([]) # -> [] (list)

110

mempty({}) # -> {} (dict)

111

mempty((1, 2)) # -> (0, 0) (tuple)

112

113

# Mappend instances

114

mappend(1, 2) # -> 3 (int addition)

115

mappend("a", "b") # -> "ab" (str concatenation)

116

mappend([1], [2]) # -> [1, 2] (list concatenation)

117

mappend({"a": 1}, {"b": 2}) # -> {"a": 1, "b": 2} (dict merge)

118

119

# Functor instances

120

fmap([1, 2, 3], lambda x: x * 2) # -> [2, 4, 6] (list)

121

fmap((1, 2, 3), lambda x: x * 2) # -> (2, 4, 6) (tuple)

122

123

# Applicative instances

124

pure([], 42) # -> [42] (list)

125

apply([1, 2], [lambda x: x * 2, lambda x: x + 1]) # -> [2, 4, 2, 3]

126

```

127

128

#### Usage Examples

129

130

```python

131

from lenses.typeclass import mempty, mappend, fmap

132

133

# Working with monoids

134

empty_list = mempty([1, 2, 3]) # []

135

combined = mappend([1, 2], [3, 4]) # [1, 2, 3, 4]

136

137

# String concatenation through mappend

138

greeting = mappend("Hello, ", "World!") # "Hello, World!"

139

140

# Dictionary merging

141

config1 = {"debug": True, "port": 8080}

142

config2 = {"host": "localhost", "port": 3000}

143

merged = mappend(config1, config2) # {"debug": True, "port": 3000, "host": "localhost"}

144

145

# Functor mapping

146

squared = fmap([1, 2, 3, 4], lambda x: x ** 2) # [1, 4, 9, 16]

147

148

# Used internally by lenses for monoid operations

149

from lenses import lens

150

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

151

combined_lists = lens.Each().get_monoid()(data) # [1, 2, 3]

152

```

153

154

### Const Functor

155

156

Constant functor used internally for lens getting operations.

157

158

```python { .api }

159

class Const:

160

"""Functor that ignores the wrapped type and preserves constant value."""

161

def __init__(self, item: C) -> None: ...

162

163

def map(self, func: Callable[[A], B]) -> Const[C, B]:

164

"""Ignores function, returns Const with same value."""

165

166

def pure(self, item: D) -> Const[D, B]:

167

"""Creates empty Const."""

168

169

def apply(self, fn: Const[C, Callable[[A], B]]) -> Const[C, B]:

170

"""Combines constant values using mappend."""

171

172

def unwrap(self) -> C:

173

"""Extract the constant value."""

174

175

def __eq__(self, other: object) -> bool: ...

176

```

177

178

#### Usage Examples

179

180

```python

181

from lenses.const import Const

182

183

# Const preserves values through transformations

184

const_val = Const(42)

185

mapped = const_val.map(lambda x: x * 1000) # Still Const(42)

186

print(mapped.unwrap()) # 42

187

188

# Used internally by lens operations

189

# This is mostly internal to the lens library

190

```

191

192

### Identity Functor

193

194

Identity wrapper functor used internally for lens setting operations.

195

196

```python { .api }

197

class Identity:

198

"""Simple wrapper functor that preserves identity."""

199

def __init__(self, item: A) -> None: ...

200

def unwrap(self) -> A: ...

201

def map(self, func: Callable[[A], B]) -> Identity[B]: ...

202

```

203

204

### Hooks System

205

206

Extension system allowing custom data types to work with lenses.

207

208

```python { .api }

209

# Core hook functions (using singledispatch)

210

def contains_add(container, item):

211

"""Add item to container."""

212

213

def contains_remove(container, item):

214

"""Remove item from container."""

215

216

def from_iter(prototype, iterator):

217

"""Reconstruct object from iterator."""

218

219

def setattr(obj, name, value):

220

"""Set object attribute."""

221

222

def setitem(obj, key, value):

223

"""Set container item."""

224

225

def to_iter(obj):

226

"""Convert object to iterator."""

227

```

228

229

#### Extending with Custom Types

230

231

```python

232

from lenses.hooks import from_iter, to_iter

233

from functools import singledispatch

234

235

# Example: Adding support for custom collection type

236

class MyList:

237

def __init__(self, items):

238

self._items = list(items)

239

240

def __iter__(self):

241

return iter(self._items)

242

243

# Register hooks for your type

244

@from_iter.register(MyList)

245

def _mylist_from_iter(prototype, iterator):

246

return MyList(iterator)

247

248

@to_iter.register(MyList)

249

def _mylist_to_iter(obj):

250

return iter(obj._items)

251

252

# Now MyList works with lenses

253

from lenses import lens

254

my_data = MyList([1, 2, 3, 4])

255

doubled = lens.Each().modify(lambda x: x * 2)(my_data) # MyList([2, 4, 6, 8])

256

```

257

258

### Pyrsistent Integration

259

260

Optional integration with the pyrsistent library for enhanced immutable data structures.

261

262

```python { .api }

263

# Automatic registration when pyrsistent is available

264

# Supports: PVector, PList, PMap, PSet, etc.

265

266

# No additional imports needed if pyrsistent is installed

267

# pip install pyrsistent

268

```

269

270

#### Usage Examples

271

272

```python

273

# With pyrsistent installed

274

import pyrsistent as pyr

275

from lenses import lens

276

277

# Works automatically with pyrsistent collections

278

plist = pyr.v(1, 2, 3, 4) # PVector

279

doubled = lens.Each().modify(lambda x: x * 2)(plist) # PVector([2, 4, 6, 8])

280

281

pmap = pyr.m(a=1, b=2, c=3) # PMap

282

incremented = lens.Values().modify(lambda x: x + 1)(pmap) # PMap({'a': 2, 'b': 3, 'c': 4})

283

```

284

285

### Functorisor

286

287

Advanced functor adapter utilities for internal lens operations.

288

289

```python { .api }

290

class Functorisor:

291

"""Functor adapter for complex lens operations."""

292

# Internal implementation details

293

# Not typically used directly by end users

294

```

295

296

### Method Shortcuts

297

298

The lens system provides convenient method shortcuts for common operations.

299

300

```python { .api }

301

# Available on lens objects:

302

# call_methodname(*args, **kwargs) - shortcut for call('methodname', *args, **kwargs)

303

# call_mut_methodname(*args, **kwargs) - shortcut for call_mut('methodname', *args, **kwargs)

304

```

305

306

#### Usage Examples

307

308

```python

309

from lenses import lens

310

311

# Method call shortcuts

312

data = ['hello', 'world', 'python']

313

314

# Regular method calls

315

uppercased1 = lens.Each().call('upper')(data) # ['HELLO', 'WORLD', 'PYTHON']

316

317

# Shortcut syntax

318

uppercased2 = lens.Each().call_upper()(data) # ['HELLO', 'WORLD', 'PYTHON']

319

320

# Mutable method shortcuts

321

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

322

sorted_data = lens.Each().call_mut_sort()(data) # [[1, 2, 3], [4, 5, 6]]

323

```

324

325

### Arithmetic and Comparison Operations

326

327

Lens objects support arithmetic and comparison operations through the modify interface.

328

329

```python { .api }

330

# Arithmetic operations (via modify)

331

lens_obj + value # Equivalent to lens_obj.modify(lambda x: x + value)

332

lens_obj - value # Equivalent to lens_obj.modify(lambda x: x - value)

333

lens_obj * value # Equivalent to lens_obj.modify(lambda x: x * value)

334

lens_obj / value # Equivalent to lens_obj.modify(lambda x: x / value)

335

# ... and many more operators

336

337

# Comparison operations

338

lens_obj == value # Equivalent to lens_obj.modify(lambda x: x == value)

339

lens_obj < value # Equivalent to lens_obj.modify(lambda x: x < value)

340

# ... and other comparison operators

341

```

342

343

#### Usage Examples

344

345

```python

346

from lenses import lens

347

348

# Arithmetic operations

349

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

350

incremented = (lens.Each() + 1)(data) # [2, 3, 4, 5, 6]

351

doubled = (lens.Each() * 2)(data) # [2, 4, 6, 8, 10]

352

353

# Comparison operations

354

greater_than_3 = (lens.Each() > 3)(data) # [False, False, False, True, True]

355

356

# Bitwise operations (special case)

357

data = [1, 2, 3, 4]

358

bitwise_result = lens.Each().bitwise_and(5)(data) # [1, 0, 1, 4]

359

```