--
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.
For more options, visit https://groups.google.com/d/optout.
--
I think this is a very good development.
In addition, I think it means that the Signal analogue of List.filterMap urgently needs to be added to elm-lang/core (with a native implementation). Because a) it provides important functionality which b) will be impossible to write purely in Elm as soon as you outlaw incomplete pattern matches. (Unlike List.filterMap, which can be written purely in Elm without incomplete pattern matches. Everybody is welcome to prove me wrong about Signal.filterMap, of course.) And even if you don’t outlaw incomplete pattern matches outright with the next release, it is best to nudge people into using a provided Signal.filterMap as early as possible instead of everybody developing a habit of writing equivalent functionality on their own and at the price of using some variant of (\(Just x) -> x).
--
There is already such a library that could be home for Signal.filterMap, namely Apanatshka/elm-signal-extra.
But:
That library, AFAIK, so far only contains functions that can be written purely in Elm, but aren’t part of the standard libs. So it’s stuff that a user could already have in their code without resorting to Native. Without incomplete pattern matches, Jeff wouldn’t be able to include Signal.filterMap in Apanatshka/elm-signal-extra unless he makes that a library that uses JS/Native, changing its character. So I still maintain that before incomplete pattern matches are, morally or technically, outlawed, Signal.filterMap should be added to elm-lang/core. :)
Yes, my only concern is that we will need to be open to more sophisticated functions on Maybes. Rather than asking for language inclusion, this might be another reason to put together a communal 3rd party package of neat extensions to add.
--
--
Okay, so should I make a PR (adding Signal.filterMap) against your lib or the standard lib? :)
Could we have different levels of safety? There's unsafe, where a pattern match can fail, annotated, where Debug.error can be called, and safe, where all functions are total.
You'd want annotated for development, but safe for production, since you should probably be catching all errors and showing messages instead.
For the specific example, that would bring us back to where Signal.filterMap cannot be used in production code, unless it becomes part of a blessed native library (e.g., elm-lang/core). The point here is that the Debug.crash that would appear in the implementation of Signal.filterMap would be 100% certain to never be executed, just the compiler cannot be convinced of that.
Right. Maybe we need a special error, one that says "this is impossible but we're not dependently typed so we can't express that" and one that says "to do implement this case later"
What's the type of Signal.filterMap again?
Signal.filterMap : (a -> Maybe b) -> b -> Signal a -> Signal b
Another current source of runtime errors that would be nice to instead catch at compile time: http://share-elm.com/sprout/54d223ade4b05f9c59b2587b (using == at a function type). IMHO, that program should be rejected by the compiler. What is a use case where calling == at a function type seems justified?
--
Definitely the former (not emitting an event if the function produces a Nothing). That’s like in List.filterMap, where no output list element is emitted if the function produces a Nothing.
Oh nice, it's a more general form of (Signal (Maybe a) -> a -> Signal a). Are the semantics to keep the old b (not emit and event at all) when the function produces a Nothing, or to use the default? I think the former is more useful.
--
I any case, I don’t have a problem with Escardo’s equality on some specific function types, just as I don’t have a problem with equality between functions of type Bool -> Bool (because it can be implemented by exhaustive enumeration, but that should be the programmer’s job if desired). I’m having a problem with equality on arbitrary function types.
--
Yes, that does it!
But I hope you feel somewhat guilty about the Nothing -> (False, snd oldb) line. The point being that the snd oldb value there (and actually computing it) does not make much sense since you’ll never access the second component of a pair whose first component is False. But you have to put something there for type reasons, so add that dummy value. To make that aspect even more apparent, consider this version: http://share-elm.com/sprout/54d5a70be4b05f9c59b25a15. It improves upon your version in that it does not need a foldp (instead just a map in that place) and does avoid computing the snd oldb projection whose value would be ignored anyway. That version even more blatantly abuses a dummy value of type b to put into the second component of (False, _) pairs “just because one has to”. I wouldn’t want a programmer to have to write your or my version, because in both versions the Nothing ~= (False, dummy_value) “modelling” just seems wrong.
BTW, in a world like discussed by Rehno in a recent thread, where (certain) signals need not have an initial value, and thus the type of filterMap (for that kind of signals) would be just (a -> Maybe b) -> Signal a -> Signal b, one couldn’t play any of the above tricks (because no b value would be available up front to abuse), even though filterMap would still make perfect sense and be useful.
first : List a -> Maybe a
first list = case list of
[] -> Nothing
x :: xs -> Just x
What should Signal.mergeMany [] : Signal a return? It would at least need an initial value, but the type a is unknown at this point. So there is no trivial signal to put there. In a world with streams that need no initial value, things would be different.
About the general exercise: This covers only intentional runtime exceptions that occur from within the Elm part of core, but core also has a JS part. And in there live things like: https://github.com/elm-lang/core/blob/2.0.1/src/Native/Utils.js#L53-L54. Maybe there are other interesting cases?
--
BTW, two of the Dict cases with a call to crash are actually statically known to never come up. The min and max functions in which they occur are completely superfluous. See https://github.com/elm-lang/core/pull/254.
2015-05-27 7:24 GMT+02:00 Richard Feldman <richard....@gmail.com>:
--
case listOfSignals of
first :: rest -> mergeMany first rest
[] -> Debug.crash "Blowing up in user code is nicer than blowing up in library code!"I agree with Max about Signal.mergeMany []. If this throws an error, it will do so during the signal graph initialization phase. Which is already almost as good as a compile time error. (In some sense, one might say it is a compile time error, seeing the life time of an Elm program as three phases: 1. compilation from Elm to JS, 2. static computation/“compilation” of a signal graph (with embedded JS) from JS, 3. running the signal graph.)
--