Another newbie question that probably results from me not having grasped Monadic do in Haskell: I want to write a simple QuickCheck generator for well-formed URIs, using the Text.URI type from the modern-uri package. To my understanding, there are two types of monads involved here: MonadThrow for error handling upon URI construction, and Gen from QuickCheck.
Here is my attempt to implement the generator. It does not type check:
import qualified Text.URI as URI
uriGen :: Gen URI.URI
uriGen = do
sc <- elements ["https", "http", "ftps", "ftp"]
tld <- elements [".com", ".org", ".edu"]
hostName <- nonEmptySafeTextGen -- (:: Gen Text), a simple generator for printable text.
uri <- do
scheme <- URI.mkScheme sc
host <- URI.mkHost $ (hostName <> "." <> tld)
return $ URI.URI (Just scheme) (Right (URI.Authority Nothing host Nothing)) Nothing [] Nothing
return uri
My understanding is that the outer do block pertains to the Gen monad while the inner one handles MonadThrow. I attempt to unwrap the Text pieces from their Gen and then use the unwrapped Text to build up URI pieces, unwrap them from their MonadThrow, then reassemble the entire URI, and finally wrap it in a new Gen.
However, I get the following type-check error:
• No instance for (MonadThrow Gen)
arising from a use of ‘URI.mkScheme’
• In a stmt of a 'do' block: scheme <- URI.mkScheme sc
In a stmt of a 'do' block:
uri <- do scheme <- URI.mkScheme sc
host <- URI.mkHost $ (hostName <> "." <> tld)
return
$ URI.URI
(Just scheme)
(Right (URI.Authority Nothing host Nothing))
Nothing
[]
Nothing
From the error, I suspect that my intuition about unwrapping and wrapping the URI pieces is wrong. Where do I err? What would be the right intuition?
Thanks very much for your help!