Discussion:
[elm-discuss] ADT: How to know whether two values have the same constructor?
Birowsky
2017-07-16 22:33:44 UTC
Permalink
Given:

type Bla = A Int | B Int
valA1 = A 1
valA2 = A 2


Is there a way for me to check whether `valA1` has been constructed with
the constructor of `valA2`?
--
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.
David Andrews
2017-07-17 03:46:36 UTC
Permalink
You could write something like:

haveSameConstructor : Bla -> Bla -> Bool
haveSameConstructor first second =
case (first, second) of
(A _, A _) -> True
(B _, B _) -> True
_ -> False
Post by Birowsky
type Bla = A Int | B Int
valA1 = A 1
valA2 = A 2
Is there a way for me to check whether `valA1` has been constructed with
the constructor of `valA2`?
--
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
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.
For more options, visit https://groups.google.com/d/optout.
Birowsky
2017-07-17 07:34:10 UTC
Permalink
That's not so bad. But the compiler wouldn't be able to nudge me to add a
new comparison when I add a new constructor in the Bla union.

Thanx anyways.
--
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.
David Andrews
2017-07-17 17:22:50 UTC
Permalink
Similar code, with new cases enforced by the compiler

haveSameConstructor : Bla -> Bla -> Bool
haveSameConstructor first second =
case (first, second) of
(A _, A _) -> True
(B _, B _) -> True
(A _, _) -> False
(B _, _) -> False
Post by Birowsky
That's not so bad. But the compiler wouldn't be able to nudge me to add a
new comparison when I add a new constructor in the Bla union.
Thanx anyways.
--
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
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.
For more options, visit https://groups.google.com/d/optout.
Ian Mackenzie
2017-07-18 15:31:39 UTC
Permalink
I think I would opt for the very literal

type Bla
= A Int
| B Int


type BlaConstructor
= AConstructor
| BConstructor


blaConstructor : Bla -> BlaConstructor
blaConstructor bla =
case bla of
A _ ->
AConstructor

B _ ->
BConstructor


haveSameConstructor : Bla -> Bla -> Bool
haveSameConstructor firstBla secondBla =
blaConstructor firstBla == blaConstructor secondBla

The compiler will remind you to add a new case to the blaConstructor function
when you add a new Bla constructor, and that in turn will prompt you to add
a case to the BlaConstructor type - no tricky tuple matching required. I'm
also guessing you can come up with a more meaningful name than
'constructor' (perhaps 'kind' or something) that better indicates what it
actually means for an object to have a particular constructor.
Post by David Andrews
Similar code, with new cases enforced by the compiler
haveSameConstructor : Bla -> Bla -> Bool
haveSameConstructor first second =
case (first, second) of
(A _, A _) -> True
(B _, B _) -> True
(A _, _) -> False
(B _, _) -> False
Post by Birowsky
That's not so bad. But the compiler wouldn't be able to nudge me to add a
new comparison when I add a new constructor in the Bla union.
Thanx anyways.
--
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
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.
For more options, visit https://groups.google.com/d/optout.
Allan Clark
2017-07-17 10:33:16 UTC
Permalink
If you want to have the compiler complain when you add a new constructor then:

haveSameConstructor : Bla -> Bla -> Bool
haveSameConstructor first second =
case (first, second) of
(A _, A _) -> True
(A _, _) -> False

(B _, B _) -> True
(B _, _) -> False
Post by Birowsky
That's not so bad. But the compiler wouldn't be able to nudge me to add a
new comparison when I add a new constructor in the Bla union.
Thanx anyways.
--
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
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.
For more options, visit https://groups.google.com/d/optout.
Peter Damoc
2017-07-18 15:56:27 UTC
Permalink
In theory you could use the inspection offered by toString:

sameConstructor : a -> a -> Bool
sameConstructor first second =
case ( String.words (toString first), String.words (toString second) )
of
( a :: _, b :: _ ) ->
a == b

_ ->
False


That being said, this might not be a good strategy for the future.
I've heard a rumor that toString might move to Debug and its use be
discouraged in production code.
Post by Birowsky
type Bla = A Int | B Int
valA1 = A 1
valA2 = A 2
Is there a way for me to check whether `valA1` has been constructed with
the constructor of `valA2`?
--
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
For more options, visit https://groups.google.com/d/optout.
--
There is NO FATE, we are the creators.
blog: http://damoc.ro/
--
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.
Birowsky
2017-07-18 18:03:22 UTC
Permalink
Petre, give it to me straight. Is the potential deprecation of toString the
only drawback to this approach? We need to be pragmatic here :}
--
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.
Peter Damoc
2017-07-18 18:10:09 UTC
Permalink
I cannot think of any other drawback right now.

Maybe with more information about the context where this is needed a better
option can be found.

I'm actually curious what is the use case that prompted this request as it
has a very XYproblem feel to it.
Post by Birowsky
Petre, give it to me straight. Is the potential deprecation of toString
the only drawback to this approach? We need to be pragmatic here :}
--
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
For more options, visit https://groups.google.com/d/optout.
--
There is NO FATE, we are the creators.
blog: http://damoc.ro/
--
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.
Birowsky
2017-07-18 18:25:09 UTC
Permalink
I agree. Here it goes:


type Route
= Route1 SubRoute1
| Route2 SubRoute2


Routes are coming into the app. I want to detect when the base route
changes. Example, from Route1_, to Route2 _.

(This is part of solution to a challenge where I need to keep the scroll
position of a list view upon a navigation to one of it's list items, so
that when the user goes back, he's faced with the same scroll position. The
approach that I'm taking is by not destroying the list view in the first
place. Problem there is that there might happen a buildup of multiple list
views causing memory pressure, so we still need to decide when is a good
time to destroy the list view. The way I rationalize: if after the list
item navigation, the user makes another base navigation, he doesn't care
about the scroll position of the list view. Ergo, I want to detect when
the base route changes. You can check out this behavior in the list views
in Dscova <https://dscova.com/trending/all/all/all>. I took a different
approach where I'm tracking the routes history.)
--
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.
David Andrews
2017-07-19 18:24:29 UTC
Permalink
Regarding the toString solution, there is a package which does this:
http://package.elm-lang.org/packages/ccapndave/elm-reflect/1.0.0/Reflect

Another downside I can think of is that it can only tell you if two values
have constructors with the same name. If the same name is used in multiple
files, they will appear to be equal.
Post by Birowsky
type Route
= Route1 SubRoute1
| Route2 SubRoute2
Routes are coming into the app. I want to detect when the base route
changes. Example, from Route1_, to Route2 _.
(This is part of solution to a challenge where I need to keep the scroll
position of a list view upon a navigation to one of it's list items, so
that when the user goes back, he's faced with the same scroll position. The
approach that I'm taking is by not destroying the list view in the first
place. Problem there is that there might happen a buildup of multiple list
views causing memory pressure, so we still need to decide when is a good
time to destroy the list view. The way I rationalize: if after the list
item navigation, the user makes another base navigation, he doesn't care
about the scroll position of the list view. Ergo, I want to detect when
the base route changes. You can check out this behavior in the list views
in Dscova <https://dscova.com/trending/all/all/all>. I took a different
approach where I'm tracking the routes history.)
--
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
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.
For more options, visit https://groups.google.com/d/optout.
Peter Damoc
2017-07-19 18:32:30 UTC
Permalink
Post by David Andrews
Another downside I can think of is that it can only tell you if two values
have constructors with the same name. If the same name is used in multiple
files, they will appear to be equal.
If you use raw toString, then yes... but if you are using a comparison
function like the one above, everything should be fine because it will
throw an error if you are trying to give it two different types (as in
types defined in different modules).
--
There is NO FATE, we are the creators.
blog: http://damoc.ro/
--
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.
Gabriel Sartori
2017-07-17 01:49:44 UTC
Permalink
I am not sure if this snippet would help you
type ValA = A1 | A2
type Bla = A ValA Int | B Int
valA1 = A 1 A1
valA2 = A 2 A2
--
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.
Loading...