They also don't entirely overlap. Any particular monad has more operations than just bind and return like get and put for State and that's what makes it a DSL for a specific purpose, or governs what we can do with that effect.
class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/j9Da2UIA5xo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
--
I'm going to try to make up a plausible description for an IO library:"""Most languages allow arbitrary side-effects, so any function you write may be reading a file or sending HTTP requests. To avoid the pitfalls that comes with this, Elm uses explicit effects. This means building up a data structure that represents the computation you want to run. The trick is that we don't actually run the computation immediately! Instead, we build up a data structure with type (IO Int) which specifies exactly which effects we'd like to perform at some point. To run this computation, we give it to Elm's runtime system, which will perform the specified IO operations and give us back an Int.
What is a value of type (State Int String)?
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
I'm going to try to make up a plausible description for an IO library:"""Most languages allow arbitrary side-effects, so any function you write may be reading a file or sending HTTP requests. To avoid the pitfalls that comes with this, Elm uses explicit effects. This means building up a data structure that represents the computation you want to run. The trick is that we don't actually run the computation immediately! Instead, we build up a data structure with type (IO Int) which specifies exactly which effects we'd like to perform at some point. To run this computation, we give it to Elm's runtime system, which will perform the specified IO operations and give us back an Int.But why go through the trouble of making effects explicit? Seems the same whether the code runs it or the runtime runs it! The easiest example is the Elm Debugger. If Elm code could write to disk at any moment, traveling back and forth through time could badly corrupt your files! With explicit effects, the computation is run by the runtime system, so the runtime system can just ignore all effectful computations when you are in debug mode, making it safe to travel time!"""
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
I should mention that I'm not into the decider part though. I think folks are familiar enough with callbacks by now, that it's okay to call it that if it really does need to be given an explicit name.
I am starting to like Command more and more. It feels much more concrete than computation, though perhaps not strictly better.And now that I know that the Command Pattern is a thing, with quite a lot of practical examples for an OO person, it seems pretty non-crazy to go with that. Instead of do-notation, perhaps there would be command-syntax :)(State Int String) is a command. You run the command, resulting in a String. (IO Int) is a command. You run the command, some effects are performed and you get an Int. We build up commands from other commands. Overall, this seems pretty solid!I should mention that I'm not into the decider part though. I think folks are familiar enough with callbacks by now, that it's okay to call it that if it really does need to be given an explicit name.On Sat, May 3, 2014 at 11:32 AM, Brian Slesinsky <br...@slesinsky.org> wrote:
On Fri, May 2, 2014 at 8:51 PM, Evan Czaplicki <eva...@gmail.com> wrote:
I'm going to try to make up a plausible description for an IO library:"""Most languages allow arbitrary side-effects, so any function you write may be reading a file or sending HTTP requests. To avoid the pitfalls that comes with this, Elm uses explicit effects. This means building up a data structure that represents the computation you want to run. The trick is that we don't actually run the computation immediately! Instead, we build up a data structure with type (IO Int) which specifies exactly which effects we'd like to perform at some point. To run this computation, we give it to Elm's runtime system, which will perform the specified IO operations and give us back an Int.But why go through the trouble of making effects explicit? Seems the same whether the code runs it or the runtime runs it! The easiest example is the Elm Debugger. If Elm code could write to disk at any moment, traveling back and forth through time could badly corrupt your files! With explicit effects, the computation is run by the runtime system, so the runtime system can just ignore all effectful computations when you are in debug mode, making it safe to travel time!"""How about this?"""A program running in a web browser needs a way to send HTTP requests to the server and get back a response. In Elm, we do this by creating a command that describes what we want to do. A command has a type such as (Command Int), where Int is the output of the command. To run a command, we give it to Elm's runtime system, which will execute it and give us back an Int.How do we create commands? Elm has many built-in functions to create commands that perform basic operations. [Give example] These are the basic building blocks for interacting with the outside world.We can also build our own, larger commands by combining the basic commands that Elm gives us. A command may consist of many intermediate steps and call functions while it's running to decide what to do next. We call these functions deciders, since they decide what to do but don't actually do it. Deciders have a type such as (String -> Command Int), where String is the input and Int is the output of whichever command it decides on.
Why do we have deciders instead of event handlers like in other browser languages? One example is the Elm debugger. The debugger can call a decider as many times as it likes without executing the commands it returns. This makes it easy to simulate traveling back and forth in time without sending HTTP requests to the server, which might overwrite or delete data."""I'm wondering how time-travel debugging with HTTP requests will work in practice, though. For a video game that represents game inputs using signals, the game controls are fixed and we can just pretend that the user is button-mashing and playing badly. But for a server this doesn't seem like enough. If we go back in time and change something, this will result in a different request to the server, so the server should send back a different response. Playback using canned responses might not make any sense; we're not doing a real "what-if" simulation.For example, suppose the user fills out a form and hits "save". This sends a request to the server and returns a response which is shown on the confirmation screen. On playback, if we fill out the form differently, we'll always get the same confirmation even if it makes no sense. There would be similar problems with a multiuser video game that uses a server: you shoot someone and they don't die, or you miss and they do die, or more likely the server moves you around the game ignoring your input entirely. We can't plausibly simulate what happens without simulating the server's decisions as well.When writing tests, there are l
--
Why do we have deciders instead of event handlers like in other browser languages?
But I've lost all ability to reason about the effects a command/monad may have! Does this HTTP command-monad execute an HTTP request or not? I have no idea. And I guess the big question is: do I need to?
I don't think there should be a concrete Command type that can do lots of things. "command" would be the general name for a computation we're going to run. It may or may not have effects. State does not have effects, but it is a "command" in that it is a computation we are going to run.So the Http library or IO library would be separate things. One can do HTTP requests, the other can work with stdin stdout, and stderr. That's it. If we want to read files, you'd create a separate File library with File commands.
For the sake of keeping things simple in this thread, you could put a bunch of different commands together with "nested commands" like this: Http (IO (File String))
I like purescripts's effects. The effects that are used in a do block are defined in the record type output by the do block. Its similar to your nested types example I think.
http://www.purescript.org/posts/Eff-Monad/
JavaScript ffi is done by wrapping a JavaScript function in an effect type. You can add and remove effects (ie using throw would add an error effect, then wrapping that in a catch will remove the error effect allowing you to use runPure on the result (it no longer has any effects).
Not sure if this is relevant!
Dylan Sale
Yeah, File is just for example. It would make more sense in Idris or Haskell.Are you familiar with monad transformers? This is a way to use State and Error together, for example. The order of nesting is somewhat arbitrary, but the point is that you can see in the types exactly what kind of effects will be used. This paper gets at all of this and shows a nice way to do it if you have dependent types, but it may be best to start with simpler examples of monad transformers.
Yeah, File is just for example. It would make more sense in Idris or Haskell.Are you familiar with monad transformers? This is a way to use State and Error together, for example. The order of nesting is somewhat arbitrary, but the point is that you can see in the types exactly what kind of effects will be used. This paper gets at all of this and shows a nice way to do it if you have dependent types, but it may be best to start with simpler examples of monad transformers.I can imagine have a general purpose thing that does everything, but I think that's out of the scope of what would be happening any time soon in Elm. Max New may have thoughts on this though.
On Sat, May 3, 2014 at 8:30 PM, Brian Slesinsky <bsles...@gmail.com> wrote:
On Saturday, May 3, 2014 7:21:01 PM UTC-7, Evan wrote:I don't think there should be a concrete Command type that can do lots of things. "command" would be the general name for a computation we're going to run. It may or may not have effects. State does not have effects, but it is a "command" in that it is a computation we are going to run.So the Http library or IO library would be separate things. One can do HTTP requests, the other can work with stdin stdout, and stderr. That's it. If we want to read files, you'd create a separate File library with File commands.I'm curious: is File a theoretical example, or is this something you're planning on adding? Which JavaScript API would it use in a browser?
For the sake of keeping things simple in this thread, you could put a bunch of different commands together with "nested commands" like this: Http (IO (File String))Perhaps I'm thinking too imperatively here, but this seems a bit weird to me since I'd have no notion of which way I'd want to nest the types, or even why I should modify a bunch of function signatures to call a new type of command. What does the extra structure give us?
On Sat, May 3, 2014 at 8:30 PM, Brian Slesinsky <bsles...@gmail.com> wrote:
Perhaps I'm thinking too imperatively here, but this seems a bit weird to me since I'd have no notion of which way I'd want to nest the types, or even why I should modify a bunch of function signatures to call a new type of command. What does the extra structure give us?
Extra structure means you can make more distinctions. If there's only one command type I don't know if a `Command a` is going to write to disk or display something to the user or make an HTTP request.
But this poses a problem when I want to change use my IO as an HTTP (IO a) and now I need to rewrite >>= as well (Haskell uses typeclasses to reduce the boilerplate).
On Sun, May 4, 2014 at 3:49 PM, Max New <max...@gmail.com> wrote:On Sat, May 3, 2014 at 8:30 PM, Brian Slesinsky <bsles...@gmail.com> wrote:
Perhaps I'm thinking too imperatively here, but this seems a bit weird to me since I'd have no notion of which way I'd want to nest the types, or even why I should modify a bunch of function signatures to call a new type of command. What does the extra structure give us?
Extra structure means you can make more distinctions. If there's only one command type I don't know if a `Command a` is going to write to disk or display something to the user or make an HTTP request.True, but why do you care? The only thing you can do with a command is return it to the runtime system so it will be executed.
But this poses a problem when I want to change use my IO as an HTTP (IO a) and now I need to rewrite >>= as well (Haskell uses typeclasses to reduce the boilerplate).If every command were already of type Command, you could already freely intermix commands. You wouldn't need to rewrite the >>= function (which isn't possible anyway because these are all effects handled by the runtime). It seems like rewriting >>= is an artificial problem introduced by trying to make a type distinction in the first place. Maybe it's needed in Haskell where there are lots of different monads, but it can be avoided in a new language.
Similarly, in Elm, all Elements are the same type, regardless of what they look like. In an older language, you might have multiple widget systems and need to convert between them. (In some older languages there isn't even agreement on a string type.)- Brian
--You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/j9Da2UIA5xo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
What do you mean? You don't just hand them to the runtime system, you also write libraries and share code. The more specific type conveys more information about what the computation does to the users of a module. Maybe I want to let some library print to the screen but I don't want it to access the network. Or if one of your IO types lets you set the exit code and terminate the program you might want to know if that could to happen. If you don't want to make distinctions you can just use some larger type that combines the ones you need.
What I found really helpful about Brian's Scene idea is that it's an asynchronously ending (trying not to say returning) function, but the value isn't an error. Although perhaps if we embrace two-type Commands, Scene a = Command Element a.
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
This isn't quite right. A Scene would display a (Signal Element) while running and return a different value when complete. (Think about how a dialog box works.)
or possibly run in a subview of the main UI if we can figure out how to make that work.
The entire Elm program does have a lifecycle, though. If scenes are full-screen then we could consider them Elm subprograms that encapsulate all their signals (which are scoped to the scene and inaccessible outside it). Then the signals would have the same lifecycle as the scene.
"What is (State Int String)?" It's a command. A Command? No it's like a Command, but this command is less general.
I was thinking maybe just having Effectful as a catchall. So you'd have (Effectful Int) and know it's going to do some stuff.
So maybe we really want (Effectful value state err) but things are looking pretty complex at this point.
--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/j9Da2UIA5xo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
This isn't quite right. A Scene would display a (Signal Element) while running and return a different value when complete. (Think about how a dialog box works.)Once you have your scene, you'd run it with (adding the auxiliary type) issue : a -> Signal (Command a e) -> Signal a. I'm thinking main = issue empty (constant scene). I haven't considered how a non-constant signal of scenes would work. Your scene must pass the result of the dialog box, represented as the auxiliary type, into the next scene (with bind).
Brian, I admire that you're trying to make things more standard, but I don't think we can "get away with" that design. HTTP can error with a status code and a message, and maybe the headers are valuable if you're in the middle of a protocol, or maybe it was blocked by the same origin policy, or maybe it timed out. Each effect is going to want a rich and customized error type to give lots of choices to the writer of bound functions.
The auxiliary type is what I originally called the error type. It's the second type variable of the Command, which I added.
So to answer your question, you can bind any Command to happen after your Scene is over, so long as its main type is Element. Yes, this would take over the program, and the resulting signal of Elements would be main. If you want multiple Scenes at once, it throws a monkey wrench in the entire system. If we pursue this further, we will no doubt want other combinators, so you can send an HTTP request with data from a completed Scene while also rendering a waiting indicator.
devil's advocate for a second: maybe that's just life and not such a
bad thing from the vantage point of having our code be clear and
explicit. if somebody wants to avoid that they can wrapper all their
own errors at their level into some void* and return that all the
time. but that's their decision to sweep useful information under the
carpet.
which to me somewhat argues for the "breaking changes" being a good
thing. if A depends on B depends on C and C changes *then A has a
dependency which has changed*. to ignore it is to defeat the purpose
of the dependencies.
i must assume i'm not parsing the thread well enough to understand the
middle grounds people must have proposed so far? :-)