3

I am trying to translate some code from haskell to scala language. In haskell I implemented an enum type like that :

data Rank = Jack | Queen | King | Ace | Num Int deriving (Show, Eq) 

I would Like to implement it in scala using selaled case Objects

sealed trait Rank
case object Jack extends Rank
case object Queen extends Rank
case object King extends Rank
case object Ace extends Rank
case object Num Int extends Rank

The problem that for the Num Int type i get an error. I think it should be written as one word ! Any help !

Khouloud
  • 81
  • 1
  • 1
  • 10
SaKou
  • 259
  • 1
  • 13
  • Possible duplicate of [Scala: difference between a typeclass and an ADT?](http://stackoverflow.com/questions/19081904/scala-difference-between-a-typeclass-and-an-adt) – Shoe Feb 01 '16 at 16:56
  • 1
    @Shoe: I don't think it can count as duplicate of http://stackoverflow.com/questions/19081904/scala-difference-between-a-typeclass-and-an-adt when OP's question is not even remotely about type classes. – Régis Jean-Gilles Feb 01 '16 at 17:26
  • @RégisJean-Gilles The answers found in that question represent both ADT and type classes in Haskell and Scala form which is what this question is all about. – Shoe Feb 01 '16 at 17:55
  • I guess it's debatable, but given how broad the other question is, vs how specific this one is, this does not strike me as being a good candidate for a duplicate. No doubt that the other question is related though, and in any case worth a read for SaKou. – Régis Jean-Gilles Feb 02 '16 at 09:23

1 Answers1

5

In Haskell Num is a class that requires a single type argument, such as Int, to produce a constraint such as Num Int. So in scala you should expect something like that:

case class Num(value: Int) extends Rank

Notice that scala requires you to give the argument a name, unlike haskell

Also you are missing the instances of Show and Eq defined for Rank in scala code, but that doesn't seem to be a part of the question

Archeg
  • 8,364
  • 7
  • 43
  • 90
  • Please note that it should be a `sealed case class` in this case, otherwise this will break open the seal of the `Rank` trait. (In contrast, `object`s are sealed by nature.) – Madoc Feb 01 '16 at 17:42
  • @Madoc Thanks, that's a good note, but it is not needed always - so I won't fix my answer. Usually `sealed` for enums is used so compiler could generate `match may not be exhaustive` check, and it still continues to work for `case class` even if it is not `sealed`, because case-to-case inheritance is prohibited in scala, and compiler does not worry about class-to-case inheritance (it does not influence a check). But this note still stands if you have other reasons to seal your type system – Archeg Feb 01 '16 at 17:55
  • FYI, in Haskell, `Num Int` would not be considered a "data type" but rather a "constraint". This works out about the same once type checking and "desugaring" have transformed Haskell to GHC Core (a.k.a. System FC), but in Haskell proper they are quite different. The `constraints` and `reflection` packages help work with relationships between them. – dfeuer Feb 01 '16 at 17:56
  • @Madoc Now when I think of it more - only `sealed` on base trait influence the `match may not be exhaustive` check. Everything else from the comment still stands – Archeg Feb 01 '16 at 17:57
  • @dfeuer Thanks, I'm not very good in Haskell terminology. I've made a fix, does it look ok? – Archeg Feb 01 '16 at 18:00
  • @Archeg Thank you,i am a beginner with both scala and haskell can you please explain how to take in consideration the `show` and `Eq` instances – SaKou Feb 01 '16 at 19:40
  • @SaKou Normally I'd have written that in the answer as well, but in this case you didn't provide any info on what are you trying to do and what libraries are you using. Scala itself does not provide `Show` type class and `Eq` is automatically defined for any `case class`. I'm not sure whether I can call this mechanics a type class, but it allows you to use `==` operator. If you want to implement an instance of real type classes, you would want to look at libraries like `scalaz` or `cats`, but that's definitely should be another question as these libraries have it's own problems with ADT – Archeg Feb 01 '16 at 20:17
  • @SaKou And scala provides `.toString()` for any class, which is not type class I believe but is very close by functionality to `Show`. So I'd summary that if you need `Show` and `Eq` functionality - you have them out of the box. If you want real type classes and be very haskell-like, then you need `scalaz` or `cats` – Archeg Feb 01 '16 at 20:19
  • 1
    I would like to point out that the included Haskell code, namely `data Rank = ... | Num Int` defines a *new* name `Num`, not related to the standard `Prelude.Num`, which is a data constructor and *not* a type class. So, though I don't know enough Scala to be able to tell for sure, I suspect that this answer may be predicated on a misunderstanding of the Haskell code and not quite on target. – Daniel Wagner Feb 01 '16 at 21:33
  • 1
    @DanielWagner I am aware of that, I also defined `Num` in scala that is not related to Haskell's `Prelude.Num` However my wording or haskell terminology may be wrong as I am mostly scala developer and know only a bit of haskell (and mostly it's practical side), so please correct me if I've said anything wrong. – Archeg Feb 01 '16 at 21:44
  • @Archeg: I have a hunch that the confusion comes from the fact that you said "Notice that scala requires you to give it a name, unlike haskell". In reality the Haskell version **does** require to come up with a name for it, as just like in scala `Num` is definitely a new name (that is totally unrelated with `Prelude.Num`, as pointed by Daniel Wagner). You might want to remove that sentence from your answer. – Régis Jean-Gilles Feb 02 '16 at 09:28
  • @RégisJean-Gilles In that phrase by `it` I meant the argument of the type. In haskell you can have `Num Int`, or you could have a record with `Num { value :: Int }`. But in scala you only have the latest, so you always have to give `Int` argument the name – Archeg Feb 02 '16 at 09:35
  • @Archeg No, when you extend a `sealed` type with a non-`object` type that is not `sealed`, then it is as if the base type had not been `sealed` in the first place. Try it out, I had a problem with that once. – Madoc Feb 02 '16 at 22:24
  • @Madoc I've tried. I receive a proper may not be exhaustive warning. – Archeg Feb 02 '16 at 22:44