LINUX.ORG.RU

inline explicit cast syntax?

 


0

2

Делаю Ractive Scala на курсере =)

(Далее будет property..forAll, доставшееся от scalacheck, и несколько функций, смысл которых совершенно неважен, т.к. вопрос чисто про синтаксис)

Есть кот, который превращает шота(H) в списки:

implicit def hToList(heap: H): List[Int] = if (isEmpty(heap)) Nil else findMin(heap) :: hToList(deleteMin(heap))

теперь, беру исходный кот:

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    (hToList(heapPair._1) ++ hToList(heapPair._2)).sorted == hToList(meld(heapPair._1, heapPair._2))
  }

и пользуясь вышеприведенным имплицитным мэджиком просто выбрасываю все вызовы hToList:

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) => 
    (heapPair._1 ++ heapPair._2).sorted == meld(heapPair._1, heapPair._2)
  }

Вот это красивое, годное котэ!

Но это оно не конпелируется, конпелятор кричит что нешжможло тип в правой части операции ==

Поможем ему руками:

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    val mldList: List[Int] = meld(heapPair._1, heapPair._2)
    (heapPair._1 ++ heapPair._2).sorted == mldList
  }

Вот теперь шможло!

Но это выглядит невперенно уродливо.

Вопрос, можно ли сделать как-то вот так?

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    (heapPair._1 ++ heapPair._2).sorted == (List[Int]) meld(heapPair._1, heapPair._2)
  }

т.е. прямо в линию зафигачить явный каст, не рассирая его на две строчки? И чтобы оно при этом шможло в implicit

Спасибо :)

★★★★☆
Ответ на: комментарий от BattleCoder

эта forAll из ScalaCheck так нешмогёт, ибо сигнатура такая:

 /** Converts a function into a universally quantified property */
  def forAll[A1,A2,P] (
    f: (A1,A2) => P)(implicit
    p: P => Prop,
    a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
    a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty
  ): Prop = forAll((a: A1) => forAll(f(a, _:A2)))

если интересно, количество параметров захардкожено, определено на количестве параметров от A1 вплоть до forAll[A1,A2,A3,A4,A5,A6,A7,A8,P]

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от BattleCoder

проблема в том, что я хочу намекнуть механизму имплиситов, что результат meld(h1, h2) нужно сконвертить в List[Int]

если функция meld возвращает H, и потом хочется чтобы имплисит hToList превратил это в List[Int], то вот это работать не будет:

(List[Int]) meld(h1, h2)

будет две ошибки - «ненужные скобки вокруг List[Int]», и «cannot resolve symbol meld», ибо я так понял оно просто не умеет в такую синтаксическую конструкцию

вот я и спрашиваю, как бы его обмануть так, или это неисправимый недостаток?

нет, я конечно понимаю, что можно вручную написать там функцию toList и сделать всё явно (как было в исходном примере кота), но я хочу (в качестве упражнения) максимально замаскировать касты

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 2)
Ответ на: комментарий от BattleCoder

вот, обманул, так всё работает:

def l(lst: List[Any]) = lst

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    (heapPair._1 ++ heapPair._2).sorted == l(meld(heapPair._1, heapPair._2))
  }

теперь как бы это сделать красиво, чтобы «никто ничего не заметил»?

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

А, понял. Странно, что не получается. Даже мыслей нет. Может, scala не умеет в generic преобразования?.. А если вместо H какой-нибудь Int сделать (пусть неявно число преобразует в список из элементов от 1 до этого числа, к примеру)

BattleCoder ★★★★★
()
Ответ на: комментарий от stevejobs

Подозреваю, проблема в том, что неявные преобразования работают, когда мы пытается метод вызвать, которого не существует у объекта. А к == это не относится (он у всех объектов существует).

Так что тут без явного преобразования не получится.

BattleCoder ★★★★★
()

Возможно, тебя это натолкнет

~|⇒ scala                                                       
Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45).
Type in expressions to have them evaluated.
Type :help for more information.

scala> implicit def s2l(str: String): Long = str.toLong
<console>:7: error: type mismatch;
 found   : str.type (with underlying type String)
 required: ?{def toLong: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method augmentString in object Predef of type (x: String)scala.collection.immutable.StringOps
 and method s2l of type (str: String)Long
 are possible conversion functions from str.type to ?{def toLong: ?}
       implicit def s2l(str: String): Long = str.toLong
                                             ^
<console>:7: error: value toLong is not a member of String
       implicit def s2l(str: String): Long = str.toLong
                                                 ^

scala> implicit def s2l(str: scala.collection.immutable.StringOps): Long = str.toLong
warning: there was one feature warning; re-run with -feature for details
s2l: (str: scala.collection.immutable.StringOps)Long

scala> def f(l:Long) = l * l
f: (l: Long)Long

scala> f("2")
<console>:10: error: type mismatch;
 found   : String("2")
 required: Long
              f("2")
                ^

scala> f(implicitly[scala.collection.immutable.StringOps]("2"))
res1: Long = 4

anonymous
()
Ответ на: комментарий от BattleCoder

А можно сравнивать скаловские листы как-нибудь кроме == ?

stevejobs ★★★★☆
() автор топика

ну и да, к логопеду.

anonymous
()
Ответ на: комментарий от BattleCoder

Всё, вот это уже можно считать решением!

(далеким от идеала, но всё же)

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    (heapPair._1 ++ heapPair._2).sorted == meld(heapPair._1, heapPair._2) ::: Nil
  }
stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от BattleCoder

проблема в том, что у листа нет ограниченного типом equals, и можно лист сравнивать с нелистом. Поэтому механизм имплиситов и не чувствует необходимым конвертить правую часть сравнения.

Вопрос был в том, как сделать тайпхинт. Красивое решение для листов получилось, для всего остального - вопрос!

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от BattleCoder

вот общее решение xD

ну быть не может, чтобы этого не было в стандартной библиотеке

  def cast[H](obj: H):H = obj

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    (heapPair._1 ++ heapPair._2).sorted == cast[List[Any]](meld(heapPair._1, heapPair._2))
  }
stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 2)
Ответ на: комментарий от BattleCoder

вот, теперь точно всё

import org.scalactic.ConversionCheckedTripleEquals._

  property("test7_meld_sort") = forAll { (heapPair: (H, H)) =>
    (heapPair._1 ++ heapPair._2).sorted === meld(heapPair._1, heapPair._2)
  }
stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от anonymous

Захотелось человеку поиграться с синтаксическими конструкциями и неявными преобразованию. Что ж вы цепляетесь. asInstanceOf - слишком просто и неинтересно.

BattleCoder ★★★★★
()
Ответ на: комментарий от BattleCoder

Она не умеет в generic-преобразования ибо стирание типов

LongLiveUbuntu ★★★★★
()
Ответ на: комментарий от anonymous

.asInstanceOf не заставит конпелятор запустить имплисит-конвертер. В результате этого вызова получится ересь, которая точно не пройдет ==

stevejobs ★★★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.