2017-02-06 2 views
0

Я пытаюсь определить «неизменные свойства сеттера» и общие функции для них.Scala - характеристики соответствия шаблону, которые имеют «self type», как аргумент типа, дают непроверенное предупреждение

У меня есть рабочая реализация, но я немного обеспокоен «непроверенными» предупреждениями из соответствия шаблонов. Я не совсем уверен, что я могу с этим поделать.

type Point = (Double, Double) 

trait Sizable[A] { 
    this: A => 
    def size: Point 

    /* immutable object value setter, returns a new of the same object*/ 
    def size(point: Point): A with Sizable[A] 
} 

def partitionToSizable[T](elements: List[T]): 
    (List[T], List[T with Sizable[T]]) = 
    elements.foldLeft((List[T](), List[T with Sizable[T]]()))((p, c) => 
     c match { 
     case a: T with Sizable[T] => (p._1, p._2 ++ List(a)) 
     case a => (p._1 ++ List(a), p._2) 
     }) 

Приведенный выше код демонстрирует проблему.

Я даже не уверен, насколько велика проблема в том, что T не отмечен, поскольку все элементы в списке будут иметь тип T, а точка соответствия шаблонов не определяет, является ли этот тип T, поскольку мы уже знаем это.

Теоретически Sizable всегда будет иметь тип T из-за подписи его закрывающей функции.

Если у вас нет другого решения, я бы хотя бы хотел подавить предупреждение. @unchecked аннотации, похоже, не подавляют предупреждение.

Если я изменить случай с: T с Sizable [T] случаю а: Sizable [_] не будет компилироваться, так как тип результата, очевидно, не подтверждают Т.

ClassTags или TypeTags может решить но я подозреваю, что они действительно не нужны. (также может иметь служебные издержки производительности и TypeTags не работают с Scala.js)

+0

Зачем вам такое сложное определение Sizeable? Это напоминает мне определение одиночного связанного списка. –

+0

@ Антон Данилов, что вы имеете в виду? Это не список, он предоставляет общий, общий интерфейс для создания нового неизменяемого экземпляра с одним изменением свойства. Кроме того, речь идет не о Sizable, это просто пример концепции. Если вы знаете какой-нибудь лучший метод для этого, я бы воспринял это как ответ. –

+0

Вам известно о копировании класса case? Это более общая и мощная альтернатива тому, что я считаю «размерным». – Simon

ответ

1

Я думаю, что только case a: Sizable[T @unchecked] => a.size((15,20)) должен работать.

+0

Это само по себе не решает проблему, так как тогда мне нужно будет передать результат этого блока в T, поэтому он будет похож на 'a.size ((15,20)). AsInstanceOf [T]'. Я бы хотел избежать использования asInstanceOf. Кроме того, он не отвечает на более насущный вопрос, есть ли лучшее решение, или если это действительно проблема, что он не отмечен. –

+0

Зачем вам нужно бросать? 'Sizable [T] .size (Point)' возвращает 'T'. –

+0

Я не согласен с вами, компилятор Scala делает 'Ошибка: (125, 20) несоответствие типа; найдено: Позиционный [T] с материалом с существенным [T @unchecked] требуется: T' –

1

Основная проблема здесь: partitionToSizable. Он принимает List[T], а затем пытается разбить его на List[T]и a List[T with Sizable[T]]. Вы берете список одного типа, а затем говорите, что один тип T на самом деле два разных типа: T и T with Sizable[T]. Это указывает на проблему с дизайном вашего типа. Я бы рекомендовал сначала решить это.

Одним из решений может быть признание того, что вещи, которые являются значимыми, и вещи, которые не являются значительными, должны быть представлены как два разных типа. Затем вы можете использовать следующую подпись:

def partitionToSizable[T1, T2 <: Sizable[T2]](
    elements: List[Either[T1, T2]]): (List[T1], List[T2]) 

Тогда вам не нужно бросать; вы можете совпадать с рисунком или складывать на Either.

+0

Я хотел упростить свой вопрос, но теперь этого может не хватать. То, что вы предлагаете, по-прежнему будет нуждаться в методе разбиения, поскольку оно будет содержать T (и подтипы T) в одном списке. Их невозможно отделить, так как есть другие подобные черты, такие как Positionable, Colorable и т. Д. ... и их комбинации. Это графические элементы, где в некоторых случаях порядок может иметь значение. С изменчивым подходом это намного проще, так как вам не нужно ничего возвращать, и вы можете просто соответствовать «case a: Sizable». Дизайн типа может быть не лучшим, но у меня нет лучших идей, сохраняя его универсальным. –

+0

@ MátéMagyar да, я думаю, что мне не хватает того, чего вы пытаетесь достичь с этим разделением. Обычно с графическими элементами я бы не собирал их вместе в одно ведро, а затем пытался их разделить; Я бы держал их очень раздельными. – Yawar

+0

Я не уверен, как их разделить, так как сейчас есть 120 возможных комбинаций черт, которые используются сейчас (и я думаю, что будет больше, это факторная фигура, поэтому, если я добавлю еще одну, до 720), что, очевидно, не сработает. Одна вещь, которая может работать, - это HLists, но это также потребовало бы, чтобы полиморфные функции работали с ними, и это значительно повысило бы сложность. Цель состоит в том, что у меня есть функция, которая будет упорядочивать элементы и изменять размеры элементов, которые могут быть изменены в случае необходимости (чтобы заполнить/вставить в указанные ограничения) и быть универсальными. –

Смежные вопросы