I'm having trouble understanding why there are two independent f and f0 Applicative constraints in code below (requires reducers package).
import Data.Semigroup.Applicative
import Data.Semigroup.Reducer
import Data.Semigroup
-- | Foo
--
-- >>> getMax $ foo ["abc","a","hello",""]
-- 5
foo :: [String] -> (Max Int)
foo = foldReduce . map (length)
bar :: (Foldable f, Monoid m, Reducer e m) => f e -> m
bar = foldReduce
m :: Max Int
m = unit (2 :: Int)
apm :: (Applicative f) => Ap f (Max Int)
apm = unit $ pure (2 :: Int) -- ambiguous Applicative!
I think that I need to somehow tell that I want f0 ~ f where f0 is independently inferred by use of pure.
I tried to simplify:
u :: (Applicative f, Monoid m) => e -> Ap f m
u = undefined
m :: (Applicative f) => Ap f (Max Int)
m = u $ (pure (2 :: Int))
It will compile once e is changed to f e so that contexts can "unify". But I don't know how to unify with reducer context.
My goal is to foldReduce with Applicative Semigroup (if that's possible at all) so that length will be replaced with effectful version.
The standard solution is to use ScopedTypeVariables to announce that the f in the signature for apm and the f you want pure to produce are the same f. So:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Semigroup.Applicative
import Data.Semigroup.Reducer
import Data.Semigroup
apm :: forall f. Applicative f => Ap f (Max Int)
apm = unit (pure 2 :: f Int)
Don't lose the forall; it's a requirement of the extension to bring f into scope in the definition's body.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With