I'm trying to pull a value out of a monad, but keep the value, which doesn't depend on the monad, polymorphic. Specifically:
foo :: (Monad mon, Ring a) => mon a
foo = return 3
main :: IO ()
main = do
x <- foo
print (x :: Double)
print (x :: Int)
The point is that the monadic portion of the computation is expensive to compute, so I only want to do it once, while keeping the value in the monad polymorphic. All of my attempts so far:
x
the signature forall a. (Ring a) => a
)foo :: (Monad mon) => mon (forall a . (Ring a) => a)
-XNoMonomorphismRestriction
and NoMonoLocalBins
have either not worked or given errors about impredicative polymorphism, which I'm not willing to use. Is there some way to pull a polymorphic value out of a monad without impredicative polymorphism (or alternatively: is there a safe way to use impredicative polymorphism in GHC)?
Monad is a simple and powerful design pattern for function composition that helps us to solve very common IT problems such as input/output, exception handling, parsing, concurrency and other. Application becomes less error prone.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
In functional programming, a monad is a software design pattern with a structure that combines program fragments (functions) and wraps their return values in a type with additional computation.
List as a data structure is not a Monad, but the fact that Scala's List implements flatMap is what gives it its monadic super-powers. It also needs to fulfil associativity, left unit and right unit laws to qualify as a Monad.
You can work around the absence of impredicative polymorphism by wrapping the polymorphic value in a special data type.
newtype AnyRing = AnyRing (forall a. Ring a => a)
foo :: Monad m => m AnyRing
main = do
AnyRing x <- foo
print (x :: Double)
print (x :: Int)
I found another interesting solution, which came from this paper on typed, tagless, final interpreters (section 2.3).
The idea is to use a "duplicator":
data Dup a b = Dup a b
duplicate :: Dup a b -> (a,b)
duplicate (Dup a b) = (a,b)
instance (Num a, Num b) => Num (Dup a b) where
fromInteger x = Dup (fromInteger x) (fromInteger x)
...
foo :: (Monad mon, Num a) => mon a
foo = return 3
main :: IO ()
main = do
x <- foo
let (y,z) = duplicate x
print (y :: Double)
print (z :: Int)
This solution isn't as general as Li-yao Xia's (it only works when the monadic value is an instance of a type class), but it is interesting because you don't need higher-rank polymorphism.
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