Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loeb moeb swing #54

Closed
BlackCapCoder opened this issue Dec 3, 2018 · 2 comments
Closed

loeb moeb swing #54

BlackCapCoder opened this issue Dec 3, 2018 · 2 comments

Comments

@BlackCapCoder
Copy link

BlackCapCoder commented Dec 3, 2018

The pointfree article on haskell.org mentions a strange function named swing:

swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d
swing f c a = f ($ a) c

swing map :: forall a b. [a -> b] -> a -> [b]
swing any :: forall a. [a -> Bool] -> a -> Bool
swing foldr :: forall a b. b -> a -> [a -> b -> b] -> b
swing zipWith :: forall a b c. [a -> b -> c] -> a -> [b] -> [c]
swing find :: forall a. [a -> Bool] -> a -> Maybe (a -> Bool)
...

The type is very close to your moeb function, but it is a bit more general. Indeed, it turns out that moeb can be defined in terms of swing and fix:

swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d
swing f c a = f ($ a) c

moeb ::  (((a -> b) -> b) -> c -> a) -> c -> a
moeb f x = fix (\go -> f ($ go) x)
moeb f = fix . swing f

loeb = moeb fmap = fix . swing fmap

This realization really brought things together for me:

any :: Foldable t => (a -> Bool) -> t a -> Bool
-- `any` takes a predicate and a collection of things, 
-- and returns whether the predicate succeeds for
-- some value in the collection

swing any :: Foldable t => t (a -> Bool) -> a -> Bool
-- `swing any` instead takes a collection of predicates, 
-- and returns whether any of them succeeded.
-- Informally it moves the `t` from the `a` to the `(a -> Bool)`.

fix . swing any :: Foldable t => t (Bool -> Bool) -> Bool
-- `moeb any` removes the `a` entirely, instead the collection
-- is defined in terms of itself and moeb finds a fixed point.
@quchen
Copy link
Owner

quchen commented Dec 3, 2018

I don’t understand what swing does though – I can read the type and implementation, but I wouldn’t know a practical example of what it would be useful for. Löb has spreadsheets, what does swing have?

@BlackCapCoder
Copy link
Author

BlackCapCoder commented Dec 3, 2018

I don't have a canonical example (yet). My intuition is that given some function (a -> b) -> f a -> _ swing will produce f (a -> b) -> a -> _ - that is, it somehow moves the f.

Something I found really cool is what it does for fmap:

fmap                   :: Functor     f =>   (a -> b) -> f a -> f b
swing fmap             :: Functor     f => f (a -> b) ->   a -> f b
(<*>)                  :: Applicative f => f (a -> b) -> f a -> f b 

swing fmap = \fs a -> fs <*> pure a 

So swing fmap almost gives you a free Applicative!

instance Applicative [] where
  pure       = swing fmap [id]
  fs <*> [a] = swing fmap fs a
  fs <*> as  = undefined

-- Valid implementation of `ap` given Monoid:
instance Applicative [] where
  fs <*> as = mconcat $ swing fmap fs <$> as

@quchen quchen closed this as completed Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants