or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

core-lenses.mddocs/

0

# Core Lens Operations

1

2

The fundamental lens interface providing get, set, modify operations and lens composition. These core operations form the foundation of all lens-based data manipulation in the library.

3

4

## Capabilities

5

6

### UnboundLens

7

8

The main lens class that provides composable data access patterns without being bound to specific state. All lens constructors return UnboundLens instances.

9

10

```python { .api }

11

class UnboundLens:

12

def __init__(self, optic): ...

13

14

def get(self) -> StateFunction[S, B]:

15

"""Get the first value focused by the lens."""

16

17

def collect(self) -> StateFunction[S, List[B]]:

18

"""Get multiple values focused by the lens as a list."""

19

20

def get_monoid(self) -> StateFunction[S, B]:

21

"""Get values focused by the lens, merging them as a monoid."""

22

23

def set(self, newvalue: B) -> StateFunction[S, T]:

24

"""Set the focus to newvalue."""

25

26

def set_many(self, new_values: Iterable[B]) -> StateFunction[S, T]:

27

"""Set many foci to values from new_values iterable."""

28

29

def modify(self, func: Callable[[A], B]) -> StateFunction[S, T]:

30

"""Apply a function to the focus."""

31

32

def construct(self, focus: A) -> S:

33

"""Construct a state given a focus."""

34

35

def flip(self) -> UnboundLens[A, B, S, T]:

36

"""Flips the direction of the lens (requires isomorphisms)."""

37

38

def kind(self) -> str:

39

"""Returns the 'kind' of the lens."""

40

41

def __and__(self, other) -> UnboundLens:

42

"""Compose this lens with another lens or apply function to focus."""

43

44

def add_lens(self, other) -> UnboundLens:

45

"""Alias for __and__."""

46

```

47

48

#### Usage Examples

49

50

```python

51

from lenses import lens

52

53

# Basic getting

54

data = [1, 2, 3]

55

first = lens[0].get()(data) # 1

56

57

# Setting creates new data structures

58

new_data = lens[1].set(99)(data) # [1, 99, 3]

59

60

# Modifying with functions

61

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

62

63

# Lens composition with &

64

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

65

first_of_each = lens.Each()[0].collect()(nested) # [1, 3, 5]

66

67

# Function application with &

68

add_ten = lens[0] & (lambda x: x + 10)

69

result = add_ten(data) # [11, 2, 3]

70

```

71

72

### BoundLens

73

74

A lens that has been bound to specific state, providing direct access without needing to pass state as a parameter.

75

76

```python { .api }

77

class BoundLens:

78

def __init__(self, state: S, optic) -> None: ...

79

80

def get(self) -> B:

81

"""Get the first value focused by the lens."""

82

83

def collect(self) -> List[B]:

84

"""Get multiple values focused by the lens as a list."""

85

86

def get_monoid(self) -> B:

87

"""Get values focused by the lens, merging them as a monoid."""

88

89

def set(self, newvalue: B) -> T:

90

"""Set the focus to newvalue."""

91

92

def set_many(self, new_values: Iterable[B]) -> T:

93

"""Set many foci to values from new_values iterable."""

94

95

def modify(self, func: Callable[[A], B]) -> T:

96

"""Apply a function to the focus."""

97

98

def kind(self) -> str:

99

"""Returns the 'kind' of the lens."""

100

101

def __and__(self, other) -> BoundLens:

102

"""Compose this lens with another lens or apply function to focus."""

103

104

def add_lens(self, other) -> BoundLens:

105

"""Alias for __and__."""

106

```

107

108

#### Usage Examples

109

110

```python

111

from lenses import bind

112

113

# Create bound lens

114

data = {"users": [{"name": "Alice", "age": 25}, {"name": "Bob", "age": 30}]}

115

bound = bind(data)

116

117

# Direct operations without passing state

118

first_user_name = bound["users"][0]["name"].get() # "Alice"

119

updated_data = bound["users"][0]["age"].set(26)

120

121

# Composition works the same

122

all_ages = bound["users"].Each()["age"].collect() # [25, 30]

123

```

124

125

### StateFunction

126

127

A wrapper for functions that operate on state, returned by UnboundLens operations.

128

129

```python { .api }

130

class StateFunction:

131

def __init__(self, func: Callable[[S], T]): ...

132

def __call__(self, state: S) -> T: ...

133

```

134

135

#### Usage Examples

136

137

```python

138

from lenses import lens

139

140

# Get operations return StateFunctions

141

getter = lens[0].get() # StateFunction

142

value = getter([1, 2, 3]) # 1

143

144

# Set operations return StateFunctions

145

setter = lens[1].set(99) # StateFunction

146

new_list = setter([1, 2, 3]) # [1, 99, 3]

147

```

148

149

### Bind Function

150

151

Creates a BoundLens from state, providing an alternative entry point to the lens system.

152

153

```python { .api }

154

def bind(state: S) -> BoundLens[S, S, S, S]:

155

"""Returns a simple BoundLens object bound to state."""

156

```

157

158

#### Usage Examples

159

160

```python

161

from lenses import bind

162

163

# Create bound lens for immediate operations

164

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

165

bound_data = bind(data)

166

167

# Perform operations directly

168

first = bound_data[0].get() # 1

169

modified = bound_data.Each().modify(lambda x: x + 1) # [2, 3, 4, 5, 6]

170

171

# Useful for method chaining

172

result = (bind({"a": [1, 2, 3]})

173

["a"]

174

.Each()

175

.modify(lambda x: x * 2)

176

.collect()) # [2, 4, 6] from modified state

177

```

178

179

### Lens Composition

180

181

Lenses can be composed using the `&` operator to create complex data access patterns.

182

183

```python { .api }

184

# Composition operator

185

lens_a & lens_b # Compose two lenses

186

lens_a & function # Apply function to lens focus

187

```

188

189

#### Composition Examples

190

191

```python

192

from lenses import lens

193

194

# Nested data access

195

data = [{"values": [1, 2, 3]}, {"values": [4, 5, 6]}]

196

197

# Compose lenses to access nested values

198

each_first_value = lens.Each()["values"][0]

199

first_values = each_first_value.collect()(data) # [1, 4]

200

201

# Function composition

202

multiply_by_ten = lens.Each() & (lambda x: x * 10)

203

result = multiply_by_ten([1, 2, 3]) # [10, 20, 30]

204

205

# Complex composition chains

206

complex_lens = (lens["data"]

207

.Each()

208

.Filter(lambda x: x > 0)

209

["value"]

210

.modify(lambda x: x * 2))

211

```