4 ms·
Looks like a reimplementation of Wouter Swiestra's work on a functional model of IO, http://www.staff.science.uu.nl/~swier004/Publications/BeautyInTheBeast.pdf
by dons 14y ago
Looks like a reimplementation of Wouter Swiestra's work on a functional model of IO,
http://www.staff.science.uu.nl/~swier004/Publications/BeautyInTheBeast.pdf http://www.staff.science.uu.nl/~swier004/Publications/Beauty...
Author = {Wouter Swierstra and Thorsten Altenkirch},
Booktitle = {Haskell '07: Proceedings of the ACM SIGPLAN Workshop on Haskell},
Title = {Beauty in the Beast: A Functional Semantics of the Awkward Squad},
Pages = {25--36},
Location = {Freiburg, Germany},
Year = {2007}}
- ibotty 14y agohi dons, that is a nice link that i will check out. (i just read their data types a la carte because of a recommendation by you on stack overflow afair just last week.) i was wondering whether it is possible to restructure the io monad into smaller monads that only do more restricted things. is it possible to do something like that w/o breaking backwards compatibility? and if so, is it possible to really do so in the haskell standards process? i'd really like to reason about programs by looking at a type signature like cat :: FilePath → Term (Teletype :+: FileSystem) () instead of cat :: FilePath → IO ()
- Evbn 14y agoI seem to recall ken shan writing about this. But I can't remember much now. I feel like it is related to "regions" modeling.
- evincarofautumn 14y agoThis kind of thing is usually done with typeclasses. You have the “real” monad, but you only use it via the restricted interface allowed by the typeclass constraints. Off the top of my head: class (MonadIO m) => MonadTT m where ttGetLine :: m String ttGetLine = liftIO getLine ttPutStrLn :: String -> m () ttPutStrLn = liftIO . putStrLn class (MonadIO m) => MonadFS m where fsReadFile :: FilePath -> m String fsReadFile = liftIO . readFile cat :: (MonadTT m, MonadFS m) => FilePath -> m () In reality I don’t think I would structure it quite this way, but you get the general idea. Code to interfaces, not to implementations.
- evincarofautumn 14y agoOkay, now that I have a moment, here’s how to do it with proper encapsulation. The previous example let you perform arbitrary IO with “liftIO”, which is exactly not what you want. class MonadTT m where ttGetLine :: m String ttPutStrLn :: String -> m () instance MonadTT IO where ttGetLine = getLine ttPutStrLn = putStrLn class MonadFS m where fsReadFile :: FilePath -> m String instance MonadFS IO where fsReadFile = readFile cat :: (MonadTT m, MonadFS m) => FilePath -> m ()
- ibotty 14y agoyou are of course right, that that would work. i was wondering more whether it is possible to structure the io monad (using algebras as in data types a la carte) or as you did here while _preserving backwards compatability_. right now io is very broad and can be pretty much everything. it should be more fine-grained. (i still have to look into safe haskell and it's rio, but my superficial look says, it's something different.)
- crntaylor 14y agoWhen someone says I've reimplemented some of Wouter Swiestra's work, I can't help but feel that's a massive compliment. Thanks!