Почему я думаю, что статически печатать на более слабый тип, чем РНК, не очень хорошая идея.Это действительно должен быть комментарий (потому что это скорее мнение, но это будет сложнее читать).От вашего комментария до моего комментария:
Почему бы и нет?Как подкласс IndexedSeq [Base], RNA может делать все, что IndexedSeq [Base], согласно принципу подстановки Лискова.Иногда все, что вы знаете, это то, что это IndexedSeq, и вы все еще ожидаете, что фильтр, карта и друзья сохранят ту же конкретную реализацию.Фактически, фильтр делает это - но не сопоставление
filter
делает это, потому что компилятор может статически гарантировать это.Если вы сохраняете элементы из определенной коллекции, вы получаете коллекцию того же типа.map
не может гарантировать, что это зависит от передаваемой функции.
Моя точка зрения больше касается действия , явно указывающего тип и ожидающего большего, чем то, что он может доставить .Как пользователь коллекции RNA, я могу написать код, который зависит от определенных свойств этой коллекции, таких как эффективное представление памяти.
Итак, давайте предположим, что в val rna: IndexedSeq[Base]
я утверждаю, что rna
есть просто и IndexedSeq
.Несколькими строками позже я вызываю метод doSomething(rna)
, где я ожидаю эффективного представления памяти, что будет лучшей подписью для этого?def doSomething[T](rna: IndexedSeq[Base]): T
или def doSomething[T](rna: RNA): T
?
Я думаю, что это должно быть последним.Но если это так, то код не будет компилироваться, потому что rna
не является статически RNA
объектом.Если сигнатура метода должна быть первой, то, по сути, я говорю, что меня не волнует эффективность представления памяти.Поэтому я думаю, что явное указание более слабого типа, но ожидание более сильного поведения, является противоречием.Вот что вы делаете в своем примере.
Теперь я вижу, что даже если бы я сделал:
val rna = RNA(A, G, T, U)
val rna2 = doSomething(rna)
, где кто-то еще писал:
def doSomething[U](seq: IndexedSeq[U]) = seq.map(identity)
Я быхотелось бы, чтобы rna2
был RNA
объектом, но этого не произойдет ... Это означает, что этот кто-то другой должен написать метод, который принимает CanBuildFrom
, если они хотят, чтобы вызывающие абоненты получали более конкретные типы:
def doSomething[U, To](seq: IndexedSeq[U])
(implicit cbf: CanBuildFrom[IndexedSeq[U], U, To]) = seq.map(identity)(cbf)
Тогда я мог бы позвонить: val rna2: RNA = doSomething(rna)(collection.breakOut)