Does the underscore short-circuit

I am trying to replicate the short-circuiting behaviour of (&&). Would Elm translate this code to only evaluate the second argument if the first were True?

(&&) : Bool -> Bool -> Bool
(&&) a =
    case a of
        False -> \_ -> False
        True -> id

The documentation says AFAIK “discards the input”. Is the elm/compiler optimizing it then as shortcircuit?
If it doesn’t, how could I implement short circuiting as frictionless as possibe? The best I could come up with is:

type Bool = Bool BVal
type BVal 
    = True
    | False

true : Bool
true = Bool True

false : Bool
false = Bool False
(&&) : Bool -> Bool -> Bool
(&&) (Bool a) =
    case a of
        False -> \_ -> Bool False
        True -> id

but that’s rather ugly IMO and causes horrible code.

I have been digging in elm/compiler for two hours right now, and am unable to test/verify my assumption.

Context: elm-in-elm Issue

No, it doesn’t short-circuit. You can try it out like this:

Debug.log is quite a useful tool to figure out if something gets executed or not.

I’m afraid the only option is to use explicit thunks.


(&&) : Bool -> (() -> Bool) -> Bool

Thanks for the quick reply!
Nice trick with Debug.log, why didn’t I come up with it? :man_facepalming:

and : Bool -> (() -> Bool) -> Bool
and a b =
    case a of
        False ->

        True ->
            b ()

would be your implementation? Isn’t that basically how lazy works :stuck_out_tongue_winking_eye:?

So the second Bool needs always an lambda prepended? as in

and (isShining sun) 
    (\() -> isGreen grass)

or can I somehow wrap the lambda expression away?

lazy : a -> () -> a
lazy x () = x

and (isShining sun) 
    (lazy <| isGreen grass)

causes x to be evaluated directly again, doesn’t it?

Yeah I’m afraid there isn’t much of a way to get from explicit thunks if you want to control when stuff is evaluated.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.