Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the alternative to `Seq.contains` which fails on type mismatch?

Similar to this Scala: Why does Seq.contains take an Any argument, instead of an argument of the sequence type?

If you do Seq(1, 2, 3).contains("dasdas")

This compiles and always returns false. Is there an alternative which throws a type error ? This seems to a be major wtf where the contains always returns false and is super easy to miss in code reviews.

like image 986
Prakash Rajagaopal Avatar asked Jul 09 '19 01:07

Prakash Rajagaopal


2 Answers

You can enable -Xfatal-warnings and -Ywarn-infer-any to make it fail when there is type mismatch.
That also works for equality checks ==.

Here is an example of what I use in my build.sbt to avoid weird Scala like you are experiencing:

scalacOptions ++= Seq(
  "-deprecation",
  "-explaintypes",
  "-feature",
  "-language:higherKinds",
  "-unchecked",
  "-Xcheckinit",
  "-Xfatal-warnings",
  "-Xfuture",
  "-Xlint",
  "-Yno-adapted-args",
  "-Ypartial-unification",
  "-Ywarn-dead-code",
  "-Ywarn-inaccessible",
  "-Ywarn-infer-any",
  "-Ywarn-nullary-override",
  "-Ywarn-nullary-unit",
  "-Ywarn-numeric-widen",
  "-Ywarn-unused"
) ++ (
  if (scalaVersion.value.startsWith("2.11")) Seq.empty
  else Seq("-Ywarn-extra-implicit")

There is great article from Rob Norris on those:
https://tpolecat.github.io/2017/04/25/scalac-flags.html

FYI: Universal equality will be replaced by Multiversal equality in Scala 3 to address your issue:
http://dotty.epfl.ch/docs/reference/contextual/multiversal-equality.html

like image 99
Joan Avatar answered Sep 26 '22 16:09

Joan


You can write a extension method to only accept the defined type,

implicit class ListOps[A](list: List[A]) {
  def typeSafeContains(a: A) = list.contains(a)
}

List(1, 2, 3).typeSafeContains(1)
List(1, 2, 3).typeSafeContains("does not work") //type mismatch error;

Off-topic but I checked haskell has typesafe contains

Prelude> elem 1 [1,2,3]
True

Prelude> elem "should not work" [1,2,3]

<interactive>:6:25: error:
    • No instance for (Num [Char]) arising from the literal ‘1’
    • In the expression: 1
      In the second argument of ‘elem’, namely ‘[1, 2, 3]’
      In the expression: elem "should not work" [1, 2, 3]
like image 33
prayagupa Avatar answered Sep 23 '22 16:09

prayagupa