Logs: freenode/#haskell
| 2021-04-23 17:08:44 | × | mason_ quits (~bc8134e3@1582020-static.lxtnkya3.metronetinc.net) (Quit: CGI:IRC (Session timeout)) |
| 2021-04-23 17:09:39 | × | ericsagnes quits (~ericsagne@2405:6580:0:5100:2722:6cc:f3d:a92d) (Ping timeout: 260 seconds) |
| 2021-04-23 17:12:19 | × | stree quits (~stree@68.36.8.116) (Ping timeout: 252 seconds) |
| 2021-04-23 17:15:25 | <jrp> | Hi, a design pattern / idiom question ... I am writing a mini Forth interpreter. |
| 2021-04-23 17:15:40 | <jrp> | The core type is a State monad that carries the stacks, dictionary, etc |
| 2021-04-23 17:15:50 | <jrp> | -- | An instruction, the implementation of a /word/. |
| 2021-04-23 17:15:59 | <jrp> | type Forth w a r = CME.ExceptT VMSignal (StateT (VM w a) IO) r |
| 2021-04-23 17:16:09 | <jrp> | -- | The result of interpreting an instruction: Left = exit, Right () = continue |
| 2021-04-23 17:16:18 | <jrp> | type ForthStep w a = Forth w a (Either () ()) |
| 2021-04-23 17:16:30 | <jrp> | next :: ForthStep w a |
| 2021-04-23 17:16:39 | <jrp> | next = return $ Right () |
| 2021-04-23 17:16:49 | <jrp> | exit :: ForthStep w a |
| 2021-04-23 17:16:57 | <jrp> | exit = return $ Left () |
| 2021-04-23 17:17:06 | <jrp> | forthBlock :: [ForthStep w a] -> ForthStep w a |
| 2021-04-23 17:17:07 | <geekosaur> | a pastebin might e more appropriate |
| 2021-04-23 17:17:13 | <geekosaur> | @where paste |
| 2021-04-23 17:17:14 | <lambdabot> | Help us help you: please paste full code, input and/or output at e.g. https://paste.tomsmeding.com |
| 2021-04-23 17:17:59 | <jrp> | https://paste.tomsmeding.com/wpCgSxV1 |
| 2021-04-23 17:18:18 | <jrp> | My questions: |
| 2021-04-23 17:18:26 | → | sophie_ joins (~sophie@117.222.66.195) |
| 2021-04-23 17:18:27 | <jrp> | * Is Either () () the best way of representing exit / next execution choices or is there a better idiom? |
| 2021-04-23 17:18:36 | <jrp> | * Is there a more idiomatic way of writing forthBlock, which is intended to exit from interpreting the current list of instructions, retaining what has been sone so far, perhaps as some sort of fold? |
| 2021-04-23 17:20:28 | <monochrom> | Either () () is the 2nd worst way. |
| 2021-04-23 17:20:32 | <geekosaur> | the Either looks to me like a verbose way of writing a Bool, or maybe a type: data Result = Stop | Continue |
| 2021-04-23 17:20:37 | → | nut joins (~gtk@roc37-h01-176-170-197-243.dsl.sta.abo.bbox.fr) |
| 2021-04-23 17:20:46 | <monochrom> | The best way is defining your own algebraic data type. |
| 2021-04-23 17:21:03 | <monochrom> | Especially since you also get to choose meaningful names. |
| 2021-04-23 17:21:22 | <raehik> | what's the 1st worst way! Just () ? haha |
| 2021-04-23 17:21:30 | <monochrom> | Bool |
| 2021-04-23 17:21:41 | <geekosaur> | probably Bool, since it has too many other possible meanings |
| 2021-04-23 17:22:07 | → | ericsagnes joins (~ericsagne@2405:6580:0:5100:243e:56b2:17ce:1eff) |
| 2021-04-23 17:22:57 | <monochrom> | forthBlock is a foldr. |
| 2021-04-23 17:23:15 | <jrp> | OK but if I define my own ADT will I not have to write a bunch of Functor, Monad , etc, instances? |
| 2021-04-23 17:23:17 | <monochrom> | But I don't know which one is more idiomatic. Using foldr or writing your own recursion. |
| 2021-04-23 17:23:26 | <monochrom> | People can fight religious wars on that. |
| 2021-04-23 17:24:03 | <monochrom> | Where are you using Either() as a Functor or Applicative or Monad? |
| 2021-04-23 17:25:10 | → | stree joins (~stree@68.36.8.116) |
| 2021-04-23 17:26:41 | → | zva joins (~zava@ip5f5bdf0f.dynamic.kabel-deutschland.de) |
| 2021-04-23 17:26:53 | <jrp> | Probably nowhere at present unless there is some better forthBlock that could use it. Is it really a foldr, as the Left () case returns a Right () |
| 2021-04-23 17:27:27 | <gnumonic> | the compiler can derive a lot of classes for you if you do need the instances fwiw |
| 2021-04-23 17:27:40 | <geekosaur> | doesn't seem to be much room for any of those instances since Either () () carries only one piece of information |
| 2021-04-23 17:27:51 | ← | jakalx parts (~jakalx@base.jakalx.net) ("Error from remote client") |
| 2021-04-23 17:27:51 | × | HiRE quits (~HiRE@104.128.237.40) (Ping timeout: 250 seconds) |
| 2021-04-23 17:27:55 | <geekosaur> | and Functor and Applicative just pass that through |
| 2021-04-23 17:28:25 | <jrp> | Maybe () won't work at it will throw away the computations so far on hitting a Nothing |
| 2021-04-23 17:28:57 | <monochrom> | Either()() is Bool. No one asks how to make Bool a Functor. |
| 2021-04-23 17:28:59 | → | jakalx joins (~jakalx@base.jakalx.net) |
| 2021-04-23 17:29:57 | → | jneira[m] joins (~jneira@20.red-176-83-69.dynamicip.rima-tde.net) |
| 2021-04-23 17:30:03 | <geekosaur> | and Maybe () has no computations to throw away |
| 2021-04-23 17:30:17 | <jrp> | OK, so suppose we have data StepResult = Next | Exit deriving ... |
| 2021-04-23 17:30:31 | <monochrom> | forthBlock = foldr (\i r -> i >>= either (\_ -> next) (\_ -> r)) next |
| 2021-04-23 17:31:03 | <geekosaur> | you're confusing the Forth monad with one of the pieces of information it carries. |
| 2021-04-23 17:32:05 | <jrp> | geekosaur of one of the ForthBlock steps produces a Nothing (exit) the whole block produces Nothing, rather than Just () |
| 2021-04-23 17:32:06 | <geekosaur> | now, you do have to worry about whether the ExceptT throws away the inner StateT on exception |
| 2021-04-23 17:32:28 | → | lordcirth__ joins (~lordcirth@2607:f2c0:95b3:4400:11af:5eb6:2b18:3df9) |
| 2021-04-23 17:32:35 | <jrp> | Ah |
| 2021-04-23 17:32:51 | <geekosaur> | what'[s the difference between Nothing and Left () or False? |
| 2021-04-23 17:34:00 | <geekosaur> | there's no extra content to be thrpown away. the actual result you want is probably inside the StateT (VM w a), which sticks around regardless of what value it's attached to |
| 2021-04-23 17:34:47 | × | lordcirth_ quits (~lordcirth@2607:f2c0:95b3:4400:11af:5eb6:2b18:3df9) (Ping timeout: 250 seconds) |
| 2021-04-23 17:35:32 | <jrp> | Ah yes, sorry. I think that I'd tried forthBlock = foldl1 (>>) earlier on and it didn't work |
| 2021-04-23 17:36:02 | × | mnrmnaugh quits (~mnrmnaugh@unaffiliated/mnrmnaugh) (Quit: Leaving) |
| 2021-04-23 17:38:40 | <jrp> | The other approach that I'd contemplated was using the Continuation monad, but that looked fairly forbidding |
| 2021-04-23 17:39:56 | <minoru_shiraeesh> | one naive and primitive approach to implement early returning is having a flag in your StateT indicating whether it is in "early-return" mode or not. |
| 2021-04-23 17:40:17 | <minoru_shiraeesh> | if it is, then it does nothing with the current statement |
| 2021-04-23 17:41:05 | <geekosaur> | push the ExceptT down inside the StateT so an exception doesn't throw away the VM, then have exit be a specific exception value |
| 2021-04-23 17:42:05 | <jrp> | minoru_shiraeesh Yes, I had that and it seemed to work OK, but was interested in exploring alternativess |
| 2021-04-23 17:42:31 | × | jneira[m] quits (~jneira@20.red-176-83-69.dynamicip.rima-tde.net) (Remote host closed the connection) |
| 2021-04-23 17:44:05 | × | heatsink quits (~heatsink@108-201-191-115.lightspeed.sntcca.sbcglobal.net) (Remote host closed the connection) |
| 2021-04-23 17:44:33 | × | jespada quits (~jespada@87.74.37.248) (Quit: Leaving) |
| 2021-04-23 17:45:06 | × | dmytrish quits (~mitra@37.228.247.154) (Ping timeout: 240 seconds) |
| 2021-04-23 17:45:20 | <jrp> | geekosaur to turn the Forth type inside out. I'll have a look. At present it works quite well (you can type ^C and stop an execution or forked VM |
| 2021-04-23 17:45:53 | <monochrom> | geekosaur: I think you got it the other way round |
| 2021-04-23 17:45:53 | → | earthy joins (~arthurvl@deban2.xs4all.space) |
| 2021-04-23 17:45:57 | <monochrom> | @unmtl ExceptT E (StateT S IO) |
| 2021-04-23 17:45:57 | <lambdabot> | err: `ExceptT E (StateT S IO)' is not applied to enough arguments, giving `/\A. S -> IO (Either E A, S)' |
| 2021-04-23 17:45:59 | <geekosaur> | probably |
| 2021-04-23 17:46:00 | <monochrom> | err |
| 2021-04-23 17:46:02 | <monochrom> | @unmtl ExceptT E (StateT S IO) a |
| 2021-04-23 17:46:02 | <lambdabot> | S -> IO (Either E a, S) |
| 2021-04-23 17:46:21 | <geekosaur> | yeh, ok, I reversed them again |
| 2021-04-23 17:46:22 | <monochrom> | That's how to have S either way. (Pun intended!) |
| 2021-04-23 17:46:58 | → | heatsink joins (~heatsink@108-201-191-115.lightspeed.sntcca.sbcglobal.net) |
| 2021-04-23 17:48:08 | <monochrom> | Nice, unmtl knows about Λ |
| 2021-04-23 17:48:27 | <monochrom> | Does unmtl use System F? :) |
| 2021-04-23 17:48:53 | <jrp> | @unmtl ExceptT VMSignal (StateT (VM w a) IO) r |
| 2021-04-23 17:48:53 | <lambdabot> | VM w a -> IO (Either VMSignal r, VM w a) |
| 2021-04-23 17:49:08 | ← | sophie_ parts (~sophie@117.222.66.195) () |
| 2021-04-23 17:51:37 | <jrp> | Not sure I follow |
| 2021-04-23 17:52:16 | <monochrom> | The other way round would be: |
| 2021-04-23 17:52:22 | <jrp> | What would the other way around version look like |
| 2021-04-23 17:52:29 | <monochrom> | @unmtl StateT S (ExceptT E IO) a |
| 2021-04-23 17:52:29 | <lambdabot> | S -> IO (Either E (a, S)) |
| 2021-04-23 17:52:30 | → | juuandyy joins (~juuandyy@90.106.228.121) |
| 2021-04-23 17:53:30 | <jrp> | gotcha |
| 2021-04-23 17:55:33 | → | knupfer joins (~Thunderbi@i577BCD4D.versanet.de) |
| 2021-04-23 17:57:40 | <jrp> | And to complete the argument, adding something to my E type ( data VMSignal = VMEOF | VMNoInput | VMError String | VMExit | VMContinue) would allow me to use Exception to control program flow beyond handling Exceptions |
| 2021-04-23 17:58:42 | <jrp> | Cool. What does my forthBlock look like under this model? |
| 2021-04-23 17:59:06 | <geekosaur> | you don't even need VMContinue there, it'd be the Right instead of the Left. |
| 2021-04-23 17:59:36 | × | carlomagno quits (~cararell@148.87.23.4) (Remote host closed the connection) |
| 2021-04-23 17:59:52 | <monochrom> | Or you never needed your Either()(). |
All times are in UTC.