#!/usr/bin/envstack{- stack
--resolver lts-11.14
--install-ghc
runghc
--
-Wall -Werror
-}--------------------------------------------------------------------------------{-# LANGUAGE Safe #-}{-# LANGUAGE FlexibleContexts #-}{-# LANGUAGE UndecidableInstances #-}--------------------------------------------------------------------------------moduleMain(main)where--------------------------------------------------------------------------------importControl.Monad(liftM,ap)--------------------------------------------------------------------------------newtypeRIOa=RestrictedIO{rio::IOa}instanceFunctorRIOwherefmap=liftMinstanceApplicativeRIOwherepure=return(<*>)=apinstanceMonadRIOwherereturna=RestrictedIO$returna(>>=)mf=RestrictedIO$riom>>=rio.f--------------------------------------------------------------------------------class(Monadm)=>SubGranulatedCmdMmwheresout::String->m()instanceSubGranulatedCmdMRIOwheresoutx=gout$x++" [Subnulated]"-- or (both valid options)-- rout $ x ++ " [Subnulated]"class(SubGranulatedCmdMm)=>GranulatedCmdMmwheregout::String->m()instanceGranulatedCmdMRIOwheregoutx=rout$x++" [Granulated]"class(GranulatedCmdMm)=>RestrictedCmdMmwhererout::String->m()instanceRestrictedCmdMRIOwhereroutx=RestrictedIO$putStrLn$x++" [Restricted]"--------------------------------------------------------------------------------subgranulated::(SubGranulatedCmdMm)=>m()subgranulated=do-- We are still in the RIO monad, but now we have sub-granulated the-- effects, so we can only call those, but not Granulated, Restricted nor-- IO effects !!!sout"43"--gout "NONONONO Cat"--rout "NONONONO Cat"--putStrLn "NONONONO Cat"granulated::(GranulatedCmdMm)=>m()granulated=do-- We are still in the RIO monad, but now we have granulated the effects, so-- we can only call those, but not Restricted nor IO effects !!!subgranulatedgout"42"--rout "NONONONO Cat"--putStrLn "NONONONO Cat"restricted::(RestrictedCmdMm)=>m()restricted=do-- Now we are in the RIO monad, we can call Restricted and Granulated-- effects, but not IO !!!granulatedrout"41"--putStrLn "NONONONO Cat"main::IO()main=do-- Here we are in the IO monad, we can do whatever we want !!!riorestrictedputStrLn"40"