I have a lens(')
myLens' :: (Functor f) => (a -> f a) -> (s -> f s)
And I need a function
lensWithoutFunctor' :: ((a -> b) -> (f a -> f b)) -> (a -> f a) -> (s -> f s)
(The particular type I'm interested in is
type PopType x a = x -> Maybe (a, x)
which could be made into a Functor if I wanted)
Is there a better way to do this other than create a Functor-implementing newtype and then doing something involving "ala"?
Related
Let's say I have a convention in Haskell where I define a series of functions like this:
data Node = MkNode
s0 :: Node -> s -> Node
s0 a _ = a
s1 :: (s -> a) -> (a -> Node) -> s -> Node
s1 a b c = b (a c)
s2 :: (s -> a) -> (s -> b) -> (a -> b -> Node) -> s -> Node
s2 a b c d = c (a d) (b d)
s3 :: (s -> a) -> (s -> b) -> (s -> c) -> (a -> b -> c -> Node) -> s -> Node
s3 a b c d e = d (a e) (b e) (c e)
If possible, I would love to define a function sn that takes a variable number of arguments, always with this pattern. I've seen this sort of thing done before using typeclasses, but I can't quite figure out how to do it in this case. For example, I can imagine:
class NAble elt where
sn :: elt -> state -> Node
instance NAble Node where
sn elt _ = elt
But then I'm stuck. I'm not sure what the recursive definition would be. Perhaps something like:
instance (NAble b) => NAble (a -> b) where
sn eltMaker state = ss (eltMaker state) state
But that's obviously not quite right. Not sure if this is possible, but it would be cool if it were. Of course the order of the arguments can change if that helps get it right, but it'd be really nice to get this to work. Any help would be appreciated!
If you put the arguments in a slightly different order -- with the s argument coming first, and the Node-constructing function second -- it gets a lot easier. Then a type family will fix you right up:
{-# LANGUAGE TypeFamilies #-}
data Node = MkNode
class NAble t where
type Ret t s
sn :: s -> t -> Ret t s
instance NAble Node where
type Ret Node s = Node
sn s mkNode = mkNode
instance NAble t => NAble (a -> t) where
type Ret (a -> t) s = (s -> a) -> Ret t s
sn s mkNode fa = sn s (mkNode (fa s))
But let me also recommend an alternative. Look to the pattern the standard library uses:
pure :: Applicative f => ( t) -> f t
fmap :: Applicative f => (a -> t) -> f a -> f t
liftA2 :: Applicative f => (a -> b -> t) -> f a -> f b -> f t
liftA3 :: Applicative f => (a -> b -> c -> t) -> f a -> f b -> f c -> f t
Taking f~(->) s and t~Node, we get:
pure :: ( Node) -> s -> Node
fmap :: (a -> Node) -> (s -> a) -> s -> Node
liftA2 :: (a -> b -> Node) -> (s -> a) -> (s -> b) -> s -> Node
liftA3 :: (a -> b -> c -> Node) -> (s -> a) -> (s -> b) -> (s -> c) -> s -> Node
What if people who use the standard library need liftA4 or higher? Typically they will then switch to a chain of (<*>) uses instead:
(<*>) :: (s -> a -> Node) -> (s -> a) -> s -> Node
(f <*> g) s = f s (g s)
{-# MAKE_THE_PROGRAMMER_INLINE liftAn #-}
liftAn mkNode f1 f2 ... fn = pure mkNode
<*> f1
<*> f2
...
<*> fn
I've got a function that's doing something currently working with particular datatypes. I was wondering if I could make it a general. Here's a generalised version of it's signature:
f :: Monad m => ((a -> b) -> c -> d) -> (a -> m b) -> m c -> m d
If the above can't be written, perhaps the more restricted version can?
f2 :: Monad m => ((a -> a) -> b -> b) -> (a -> m a) -> m b -> m b
No, it is impossible, at least without non-termination or unsafe operations.
The argument is essentially similar to this one: we exploit f to inhabit a type which we know can't be inhabited.
Assume there exists
f :: Monad m => ((a -> b) -> c -> d) -> (a -> m b) -> m c -> m d
Specialize c ~ ()
f :: Monad m => ((a -> b) -> () -> d) -> (a -> m b) -> m () -> m d
Hence
(\g h -> f (\x _ -> g x) h (return ()))
:: Monad m => ((a -> b) -> d) -> (a -> m b) -> m d
Speciazlize d ~ a.
(\g h -> f (\x _ -> g x) h (return ()))
:: Monad m => ((a -> b) -> a) -> (a -> m b) -> m a
Speclialize m ~ Cont t
(\g h -> runCont $ f (\x _ -> g x) (cont . h) (return ()))
:: ((a1 -> b) -> a) -> (a1 -> (b -> r) -> r) -> (a -> r) -> r
Take h = const
(\g -> runCont $ f (\x _ -> g x) (cont . const) (return ()))
:: ((r -> b) -> a) -> (a -> r) -> r
Hence
(\g -> runCont (f (\x _ -> g x) (cont . const) (return ())) id)
:: ((r -> b) -> r) -> r
So, the type ((r -> b) -> r) -> r is inhabited, hence by the Curry-Howard isomoprhism it corresponds to a theorem of propositional intuitionistic logic. However, the formula ((A -> B) -> A) -> A is Peirce's law which is known to be non provable in such logic.
We obtain a contradiction, hence there is no such f.
By contrast, the type
f2 :: Monad m => ((a -> a) -> b -> b) -> (a -> m a) -> m b -> m b
is inhabited by the term
f2 = \ g h x -> x
but I suspect this is not what you really want.
There's a problem. Knowing c doesn't give you any information about which as will be passed to (a -> b). You either need to be able to enumerate the universe of as or be able to inspect the provided a arguments with something like
(forall f. Functor f => ((a -> f b) -> c -> f d)
In which case it becomes almost trivial to implement f.
Instead of trying to implement f in general, you should try to generalize your functions like ((a -> b) -> c -> d) to see if you can replace them with lenses, traversals, or something similar.
Does such a thing exist in Haskell's Prelude?
wfmap :: Functor f
=> a
-> (a -> b)
-> (b -> a)
-> (b -> f b)
-> f a
wfmap x u w g = fmap (w) (g (u x))
In a project I'm working on, I often found myself 'converting' a type to another, process it and 'converting' it back.
Reordering the arguments, as leftaroundabout suggests, allows for a tidier definition:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a
wfmap u w g = fmap w . g . u
As for library support, lens provides nifty support for isomorphisms. A bit more broadly, as Gurkenglas notes...
Functor f => (b -> f b) -> a -> f a is also called Lens' a b and is the centerpiece of the lens library.
Without diving into the details of how and why that works, one consequence is that your function might be defined as:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a
wfmap u w g = (iso u w) g
Or even:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a
wfmap = iso
wfmap is just (a specialised version of) iso, which gives out a function which can be used to convert an b -> f b function on the isomorphism "destination" to an a -> f a one on the isomorphism "source".
It is also worth mentioning mapping, which can be used for the somewhat different purpose of applying fmap on the other side of an isomorphism:
GHCi> :t \u w g -> over (mapping (iso u w)) (fmap g)
\u w g -> over (mapping (iso u w)) (fmap g)
:: Functor f => (s -> a) -> (b -> t) -> (a -> b) -> f s -> f t
GHCi> :t \u w g -> under (mapping (iso u w)) (fmap g)
\u w g -> under (mapping (iso u w)) (fmap g)
:: Functor f => (s -> a) -> (b -> a1) -> (a1 -> s) -> f b -> f a
Finally, note that iso u w can be replaced by any Iso you might find in the libraries or have predefined elsewhere.
I have stumbled on this piece of code fold ((,) <$> sum <*> product) with type signature :: (Foldable t, Num a) => t a -> (a, a) and I got completely lost.
I know what it does, but I don't know how. So I tried to break it into little pieces in ghci:
λ: :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
λ: :t (,)
(,) :: a -> b -> (a, b)
λ: :t sum
sum :: (Foldable t, Num a) => t a -> a
Everything is okay, just basic stuff.
λ: :t (,) <$> sum
(,) <$> sum :: (Foldable t, Num a) => t a -> b -> (a, b)
And I am lost again...
I see that there is some magic happening that turns t a -> a into f a but how it is done is mystery to me. (sum is not even instance of Functor!)
I have always thought that f a is some kind of box f that contains a but it looks like the meaning is much deeper.
The functor f in your example is the so-called "reader functor", which is defined like this:
newtype Reader r = Reader (r -> a)
Of course, in Haskell, this is implemented natively for functions, so there is no wrapping or unwrapping at runtime.
The corresponding Functor and Applicative instances look like this:
instance Functor f where
fmap :: (a -> b) -> (r -> a)_-> (r -> b)
fmap f g = \x -> f (g x) -- or: fmap = (.)
instance Applicative f where
pure :: a -> (r -> a) -- or: a -> r -> a
pure x = \y -> x -- or: pure = const
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
frab <*> fra = \r -> frab r (fra r)
In a way, the reader functor is a "box" too, like all the other functors, having a context r which produces a type a.
So let's look at (,) <$> sum:
:t (,) :: a -> b -> (a, b)
:t fmap :: (d -> e) -> (c -> d) -> (c -> e)
:t sum :: Foldable t, Num f => t f -> f
We can now specialize the d type to a ~ f, e to b -> (a, b) and c to t f. Now we get:
:t (<$>) -- spcialized for your case
:: Foldable t, Num f => (a -> (b -> (a, b))) -> (t f -> f) -> (t f -> (b -> (a, b)))
:: Foldable t, Num f => (f -> b -> (f, b)) -> (t f -> f) -> (t f -> b -> (f, b))
Applying the functions:
:t (,) <$> sum
:: Foldable t, Num f => (t f -> b -> (f, b))
Which is exactly what ghc says.
The short answer is that f ~ (->) (t a). To see why, just rearrange the type signature for sum slightly, using -> as a prefix operator instead of an infix operator.
sum :: (Foldable t, Num a) => (->) (t a) a
~~~~~~~~~~
f
In general, (->) r is a functor for any argument type r.
instance Functor ((->) r) where
fmap = (.)
It's easy to show that (.) is the only possible implementation for fmap here by plugging ((->) r) into the type of fmap for f:
fmap :: (a -> b) -> f a -> f b
:: (a -> b) -> ((->) r) a -> ((->) r) b
:: (a -> b) -> (r -> a) -> (r -> b)
This is the type signature for composition, and composition is the unique function that has this type signature.
Since Data.Functor defines <$> as an infix version of fmap, we have
(,) <$> sum == fmap (,) sum
== (.) (,) sum
From here, it is a relatively simple, though tedious, job of confirming that the resulting type is, indeed, (Foldable t, Num a) => t a -> b -> (a, b). We have
(b' -> c') -> (a' -> b') -> (a' -> c') -- composition
b' -> c' ~ a -> b -> (a,b) -- first argument (,)
a' -> b' ~ t n -> n -- second argument sum
----------------------------------------------------------------
a' ~ t n
b' ~ a ~ n
c' ~ a -> b -> (a,b)
----------------------------------------------------------------
a' -> c' ~ t a -> b -> (a,b)
Is there a way to create a lens that could do a similar thing to this function?
λ> :t \f -> bitraverse f f
\f -> bitraverse f f
:: (Applicative f, Bitraversable t) =>
(b -> f d) -> t b b -> f (t d d)
The specific type I'm trying to satisfy at the moment is:
something :: (Applicative f, Monad m) => (a -> f a) -> (m a, m a) -> f (m (a, a))
I've been experimenting with traverseOf and both from lens but can't seem to make the types line up.