#!/usr/bin/envstack{- stack
--resolver lts-8.21
--install-ghc
runghc
--package http-client
--package http-client-tls
--
-Wall -Werror
-}moduleGranulateEffects(main)whereimportqualifiedData.ByteString.Lazy.Char8asL8{- https://haskell-lang.org/library/http-client -}importNetwork.HTTP.Client{- https://hackage.haskell.org/package/http-client-tls -}importNetwork.HTTP.Client.TLS(tlsManagerSettings){- As Kris Jenkins (@krisajenkins) says: "IO is the SUDO of side-effects" -}getHtml::String->IOStringgetHtmlurl=do{- To get secure HTML we will need: TLS manager, request and response -}manager<-newManagertlsManagerSettingsrequest<-parseRequesturlresponse<-httpLbsrequestmanagerlethtml=L8.unpack$responseBodyresponse{- Because we aren't limiting effects, we can also log to a file -}writeFile"./logging.txt"htmlreturnhtml{- Lets granulate our effects to what we really want -}classMonadm=>MmanagerTLSmwherenewManager'::ManagerSettings->mManagerinstanceMmanagerTLSIOwherenewManager'=newManagerclassMonadm=>MrequestmwhereparseRequest'::String->mRequestinstanceMrequestIOwhereparseRequest'=parseRequestclassMonadm=>MresponsemwherehttpLbs'::Request->Manager->m(ResponseL8.ByteString)instanceMresponseIOwherehttpLbs'=httpLbs{- We update the signature and add our granulated prime functions -}getHtml'::(MmanagerTLSm,Mrequestm,Mresponsem)=>String->mStringgetHtml'url=do{- To get secure HTML we will need: TLS manager, request and response -}manager<-newManager'tlsManagerSettingsrequest<-parseRequest'urlresponse<-httpLbs'requestmanagerlethtml=L8.unpack$responseBodyresponse{- And we are no longer allowed to log to a file, only retrieve HTML -}-- writeFile "./logging.txt" html{- error:
• Couldn't match type ‘m’ with ‘IO’
‘m’ is a rigid type variable bound by
the type signature for:
getHtml' :: forall (m :: * -> *).
(MmanagerTLS m, Mrequest m, Mresponse m) =>
String -> m String
at GranulateEffects.hs:70:13
Expected type: m ()
Actual type: IO ()
• In a stmt of a 'do' block: writeFile "./logging.txt" html
In the expression:
do { manager <- newManager' tlsManagerSettings;
request <- parseRequest' url;
response <- httpLbs' request manager;
let html = L8.unpack $ responseBody response;
.... }
In an equation for ‘getHtml'’:
getHtml' url
= do { manager <- newManager' tlsManagerSettings;
request <- parseRequest' url;
response <- httpLbs' request manager;
.... }
• Relevant bindings include
getHtml' :: String -> m String (bound at GranulateEffects.hs:71:1)
-}returnhtml{- And ofc it's easier to just put everything inside the same monad -}classMonadm=>HtmlHttpsMmwherenewManager''::ManagerSettings->mManagerparseRequest''::String->mRequesthttpLbs''::Request->Manager->m(ResponseL8.ByteString)instanceHtmlHttpsMIOwherenewManager''=newManagerparseRequest''=parseRequesthttpLbs''=httpLbs{- We update the signature and add our granulated prime prime functions -}getHtml''::(HtmlHttpsMm)=>String->mStringgetHtml''url=do{- To get secure HTML we will need: TLS manager, request and response -}manager<-newManager''tlsManagerSettingsrequest<-parseRequest''urlresponse<-httpLbs''requestmanagerlethtml=L8.unpack$responseBodyresponse{- And we are still not allowed to log to a file, only retrieve HTML -}-- writeFile "./logging.txt" html{- error:
• Couldn't match type ‘m’ with ‘IO’
‘m’ is a rigid type variable bound by
the type signature for:
getHtml'' :: forall (m :: * -> *).
HtmlHttpsM m =>
String -> m String
at GranulateEffects.hs:111:14
Expected type: m ()
Actual type: IO ()
• In a stmt of a 'do' block: writeFile "./logging.txt" html
In the expression:
do { manager <- newManager'' tlsManagerSettings;
request <- parseRequest'' url;
response <- httpLbs'' request manager;
let html = L8.unpack $ responseBody response;
.... }
In an equation for ‘getHtml''’:
getHtml'' url
= do { manager <- newManager'' tlsManagerSettings;
request <- parseRequest'' url;
response <- httpLbs'' request manager;
.... }
• Relevant bindings include
getHtml'' :: String -> m String
(bound at GranulateEffects.hs:112:1)
-}returnhtmlmain::IO()main=dohtml0<-getHtml"https://www.google.dk/"html1<-getHtml'"https://www.google.dk/"html2<-getHtml''"https://www.google.dk/"print$html0print$html1print$html2