diff options
author | Viktor Dukhovni <ietf-dane@dukhovni.org> | 2021-11-08 15:35:00 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-11-10 09:16:58 -0500 |
commit | 0f852244da36778e9980c41febb39df5c335ad4a (patch) | |
tree | 43f10e21425e6a1af0034868a1652c2ade70bde8 /libraries | |
parent | 95563259847454efdacfbbff9f28de040089132f (diff) | |
download | haskell-0f852244da36778e9980c41febb39df5c335ad4a.tar.gz |
Improve ZipList section of Traversable overview
- Fix cut/paste error by adding missing `c` pattern in `Vec3`
traversable instance.
- Add a bit of contextual prose above the Vec2/Vec3 instance
sample code.
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/base/Data/Traversable.hs | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/libraries/base/Data/Traversable.hs b/libraries/base/Data/Traversable.hs index 2fbefc7ceb..a34ce3d577 100644 --- a/libraries/base/Data/Traversable.hs +++ b/libraries/base/Data/Traversable.hs @@ -1314,7 +1314,9 @@ foldMapDefault = coerce (traverse @t @(Const m) @a @()) -- -- #ziplist# -- As a warm-up for looking at the 'ZipList' 'Applicative' functor, we'll first --- look at a simpler fixed-width analogue. +-- look at a simpler analogue. First define a fixed width 2-element @Vec2@ +-- type, whose 'Applicative' instance combines a pair of functions with a pair of +-- values by applying each function to the corresponding value slot: -- -- > data Vec2 a = Vec2 a a -- > instance Functor Vec2 where @@ -1327,7 +1329,9 @@ foldMapDefault = coerce (traverse @t @(Const m) @a @()) -- > foldMap f (Vec2 a b) = f a <> f b -- > instance Traversable Vec2 where -- > traverse f (Vec2 a b) = Vec2 <$> f a <*> f b --- > +-- +-- Along with a similar definition for fixed width 3-element vectors: +-- -- > data Vec3 a = Vec3 a a a -- > instance Functor Vec3 where -- > fmap f (Vec3 x y z) = Vec3 (f x) (f y) (f z) @@ -1338,7 +1342,11 @@ foldMapDefault = coerce (traverse @t @(Const m) @a @()) -- > foldr f z (Vec3 a b c) = f a (f b (f c z)) -- > foldMap f (Vec3 a b c) = f a <> f b <> f c -- > instance Traversable Vec3 where --- > traverse f (Vec3 a b) = Vec3 <$> f a <*> f b <*> f c +-- > traverse f (Vec3 a b c) = Vec3 <$> f a <*> f b <*> f c +-- +-- With the above definitions, @'sequenceA'@ (same as @'traverse' 'id'@) acts +-- as a /matrix transpose/ operation on @Vec2 (Vec3 Int)@ producing a +-- corresponding @Vec3 (Vec2 Int)@: -- -- Let __@t = Vec2 (Vec3 1 2 3) (Vec3 4 5 6)@__ be our 'Traversable' structure, -- and __@g = id :: Vec3 Int -> Vec3 Int@__ be the function used to traverse @@ -1347,9 +1355,10 @@ foldMapDefault = coerce (traverse @t @(Const m) @a @()) -- > traverse g t = Vec2 <$> (Vec3 1 2 3) <*> (Vec3 4 5 6) -- > = Vec3 (Vec2 1 4) (Vec2 2 5) (Vec2 3 6) -- --- And since __@traverse id@__ is just 'sequenceA', we see that the effect of --- 'sequenceA' on the structure __@t@__ is to perform a matrix /transpose/. --- Below we look at an analogue of the above for 'Control.Applicative.ZipList'. +-- This construction can be generalised from fixed width vectors to variable +-- length lists via 'Control.Applicative.ZipList'. This gives a transpose +-- operation that works well for lists of equal length. If some of the lists +-- are longer than others, they're truncated to the longest common length. -- -- We've already looked at the standard 'Applicative' instance of @List@ for -- which applying __@m@__ functions __@f1, f2, ..., fm@__ to __@n@__ input |