I'm looking for a function that like foldlWithKey, but encapsulated in a monad.
I would expect it to have type
Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
but Hoogle isn't giving me anything with that type.
foldlWithKey is already very close to what you want. If you specialize a to m a you will have something that operates on values encapsulated in a monad.
foldlWithKey :: ( a -> k -> b -> a) -> a -> Map k b -> a
foldlWithKey :: (m a -> k -> b -> m a) -> m a -> Map k b -> m a
{- ^- you don't want these -^ -}
We can get rid of the two m as you don't want with >>= and return.
foldlWithKeyM :: Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
foldlWithKeyM f acc = foldlWithKey f' (return acc)
where
f' ma k b = ma >>= \a -> f a k b
#Cirdec's solution certainly works, but it has a possible problem: It nests >>=s deeply leftwards. For many (but not all!) monads, this can give stack blowup similar to when using non-strict foldl. So I'll present a different solution, which nests >>=s rightwards instead. For monads such as IO this should allow the action to be constructed and consumed lazily from the map as it is executed.
This solution is probably a bit trickier, as it uses a right fold to build up the monadic function that will eventually consume the starting value. At least I had some trouble getting the types right.
Except for the key handling, this is essentially the same method as used by Data.Foldable.foldlM.
-- Pragma needed only to give f' a type signature for sanity. Getting it
-- right almost took a piece of mine until I remembered typed holes.
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Map
foldlWithKeyM
:: forall m a k b. Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
foldlWithKeyM f start m = foldrWithKey f' return m $ start
where
f' :: k -> b -> (a -> m a) -> (a -> m a)
f' k b a2mb a = f a k b >>= a2mb
Related
In Control.Lens.Lens, there is a function
modifying :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()
which allows the value under a lens on the MonadState state to be transformed by a pure function (a -> b).
However, we may want to allow the transform function to fail in m, requiring it to have type (a -> m b).
I've looked through the lens library for such a function, but I can't find one, so I implemented:
modifyingM l f = use l >>= f >>= assign l
Which does the trick, but I was wondering if there is a function already in the lens library that will do this.
I don't see anything like that. ASetter is defined
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
so it's not powerful enough for the job (and Setter can't do it either). It turns out, on the other hand, that a Lens is a bit stronger than necessary. Let's consider, then, how to do it with a Traversal.
type Traversal s t a b =
forall f. Applicative f => (a -> f b) -> s -> f t
So
Traversal s s a b =
forall f. Applicative f => (a -> f b) -> s -> f s
Which Applicative do we want? m seems like the obvious one to try. When we pass the traversal a -> m b, we get back s -> m s. Great! As usual for lens, we'll actually only require the user to provide an ATraversal, which we can clone.
modifyingM
:: MonadState s m
=> ATraversal s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- cloneTraversal t f s
put s'
That's nice because it only traverses the state once.
Even that is overkill, really. The most natural thing is actually
modifyingM
:: MonadState s m
=> LensLike m s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- t f s
put s'
You can apply that directly to a Traversal, Lens, Iso, or Equality, or use cloneTraversal, cloneLens, cloneIso, or (in lens-4.18 or later) cloneEquality to apply it to the monomorphic variants.
There are method (>>=) :: forall a b. m a -> (a -> m b) -> m b.
How can i make method :: forall a b. m (n a) -> (a -> m (n b)) -> m (n b) where m and n is monads.
As PyRulez writes, there's no general solution for this, but given the types you report, something like the following should work.
You're going to need
import Control.Monad (join)
Using do notation, you can compose two functions, foo and bar, like this:
comp :: (a -> TargetClient (MethodResult b)) ->
(b -> TargetClient (MethodResult c)) ->
a -> TargetClient (MethodResult c)
comp foo bar x = do
f <- foo x
b <- join <$> traverse bar f
return b
If you don't like the do notation, you can reduce it all to this:
comp' :: (a -> TargetClient (MethodResult b)) ->
(b -> TargetClient (MethodResult c)) ->
a -> TargetClient (MethodResult c)
comp' foo bar x = foo x >>= fmap join . traverse bar
When you map f with bar, you'll get the monads stacked in the wrong order, so to speak, but you can use traverse to switch the stack. Even when you do that, you'll have an Either in an Either, so that's the reason you need join.
If both m and n are monads, you need an additional piece to make the composite m.n a monad as well.
What is required is a "distributive law", that is a natural morphism
forall a . n(m a) -> m(n a) (see here it comes from Beck and is also used in Street)
It then becomes easy to write the missing piece and verify it satisfies the monad laws.
I am an intermediate schemer, but only a haskell beginner. Here is my problem:
Suppose you have an associative binary operation, says (>>=). Is there a polyvariadic function p such that p (>>=) h g f e = h >>= g >>= f >>= e?
I am asking this question because this question says it is possible if the binary operation takes inputs of the same type. I wonder if this can be generalized.
EDIT-1: I try to modify the code in http://okmij.org/ftp/Haskell/vararg-fn.lhs (the section of Variable number of variably typed arguments) with little progress.
EDIT-2: Simplify the code a bit.
{-# LANGUAGE FunctionalDependencies, FlexibleInstances #-}
module Main where
class Lfold f a b | b -> a where
lfold :: (a -> (f a) -> (f a)) -> (f a) -> a -> b
instance Lfold f a (f a) where
lfold op rid x = op x rid
instance Lfold f a b => Lfold f a (a -> b) where
lfold op rid x y = lfold op (op x rid) y
test :: [String]
test = lfold (:) [] "a" "b" "c"
main :: IO ()
main = putStrLn $ show test
Yes, you can create such a function. It is very ugly however, and you will need to explicitly type every argument you are going to pass to make the compiler find the correct instance.
Starting from the polyvariadic function template you linked, I arrived at
{-# LANGUAGE FlexibleInstances, InstanceSigs, MultiParamTypeClasses #-}
class ImplicitChain m a r where
p :: m a -> r
instance Monad m => ImplicitChain m a (m a) where
p :: m a -> m a
p x = x
instance (Monad m, ImplicitChain m b r) => ImplicitChain m a ((a -> m b) -> r) where
p :: m a -> (a -> m b) -> r
p x f = p (x >>= f)
h :: Int -> [Int]
h = replicate 2
g :: Int -> [Int]
g = (:[])
f :: Int -> [Int]
f = flip enumFromTo 2
test :: [Int]
test = p [1::Int] h g f
But you were asking whether we can do more generic, so that the binary operation is an argument as well. Yes:
{-# LANGUAGE FlexibleInstances, InstanceSigs, MultiParamTypeClasses, UndecidableInstances #-}
class ImplicitVariadic a b r where
p :: (a -> b -> a) -> r
instance ImplicitVariadic a b (a -> a) where
p :: (a -> b -> a) -> a -> a
p _ x = x
instance (ImplicitVariadic a b (a -> r)) => ImplicitVariadic a b (a -> b -> r) where
p :: (a -> b -> a) -> a -> b -> r
p f x y = p f (f x y)
You can't (at least, not easily), because you need to know how many arguments you are getting ahead of time. Because all functions in Haskell are automatically curried, every function takes exactly one argument and returns one value. Even a simple binary operator takes one argument (the first operand) and returns a function that takes one argument (the second operand) and returns a result. That is,
a + b == (+) a b
== ((+) a) b
There is no way for your imaginary function p to know from its first argument how many other arguments are going to be given. That is, what should the type of p be?
p :: (a -> a -> a) -> a -- zero arguments?
p :: (a -> a -> a) -> a -> a -- one argument?
p :: (a -> a -> a) -> a -> a -> a -- two arguments?
p :: (a -> a -> a) -> a -> a -> a -> a -- three arguments?
Instead, the best you can do is use a fold, which takes an operation and a list of operands.
foldr (+) 0 [h, g, f, e] == h + g + f + e + 0 -- explicit first argument of 0
foldr1 (+) [h, g, f, e] == h + g + f + e -- assumes a list of at least one value
To see what I mean by "not easily", look at the implementation of printf in the Text.Printf module. Even that is not a good example, because the first argument carries information (the number of placeholders in the format string) that a binary operation alone does not.
In Haskell's Monads, I can easily define the operator (>=>) as :
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
I also know that (>>=) can be expressed using (>=>): Let's call (>>=) as (..):
(..) :: Monad m => m a -> (a -> m b) -> m b
m .. k = m >=> \_ -> k
However something is not right ... could someone point what?
The idea of using a constant function (that is, \_ -> -- etc.) to make a function out of the argument which isn't a function so that you can pass it to (>=>) is sound. There are just two issues. Firstly, you are doing it to the wrong argument, as the one which isn't a function is m:
GHCi> :t \m k -> (\_ -> m) >=> k
\m k -> (\_ -> m) >=> k :: Monad m => m b -> (b -> m c) -> a -> m c
Secondly, (>=>) gives you a function (of type a -> m c in the demo just above). You have to apply it to something to get a result type that matches the one of (>>=). As that argument is irrelevant (you are ultimately feeding it to a constant function) you can just use ():
GHCi> :t \m k -> ((\_ -> m) >=> k) ()
\m k -> ((\_ -> m) >=> k) () :: Monad m => m b -> (b -> m c) -> m c
And that's it. I find it slightly prettier to use the const function rather than writing \_ ->, and so I would write it as:
(>>..) :: Monad m => m a -> (a -> m b) -> m b
m >>.. k = (const m >=> k) ()
The solution is the following:
(..) :: Monad m => m a -> (a -> m b) -> m b
m .. k =
(const m >=> k) undefined
Using const we're lifting an operation of type m a to whatever -> m a. This lifted version does not give a damn, what we pass to it so it might as well be the undefined.
So >>= :: m a -> (a -> m b) -> m b and >> :: m a -> m b -> m b.
whereas <* :: f a -> f b -> f a.
But I want something that does m a -> (a -> m b) -> m a, i.e. actually discards the computation result and keeps the original. In my case, this computation result is just an IO operation that returns () so I just need to pass the original value along.
Is there such a function? If not, how do I compose one? Haven't managed to figure it out. Thanks!
discardResult mx mf = do x <- mx
mf x
return x
Though jozefg's solution is simpler.
discard :: Monad m => m a -> (a -> m b) -> m a
discard g f = g >>= ((>>) <$> f <*> return)
Uses the Applicative instance of (->) to make it a little shorter, but is otherwise equivalent to Alexey's answer. Of course this requires Control.Applicative but since you mentioned <* I figured you already had that one.
E.g: discard getLine print reads a line, prints it and then returns the string read.