Home freenode/#haskell: Logs Calendar

Logs: freenode/#haskell

←Prev  Next→ 502,152 events total
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.