Я пытаюсь создать шаблон проектирования с trait
или class
:
class Collection(input: F[A]) {
def combineWith(other: Collection): Collection
def combineWith(other: A): Collection
}
С F
это Set
, List
, Seq
и т. д.
И A
относится к типу Item
:
class Item(....) {
def wrap: Collection[Item]
}
Я пробовал, но попал в цикл, когда для элемента требуются типы коллекции, а для коллекции требуется тип элемента, и это выходит из-под контроля, ха-ха.
Я уверен, что должен быть шаблон для повторного использования, но я не могу его найти.
Я начинаю использовать ScalaZ
, поэтому, если есть что-то, что я могу там использовать, это было бы здорово.
Конечная цель - получить пару Item <-> Collection
, в которой коллекция может принимать только элемент правильного типа и где элемент может находиться только в этой коллекции. И иметь возможность перемещаться с wrap
и добавлять коллекции:
Item +: Collection
Item |+| Item
Collection :+ Item
Collection ++ Collection
Все эти операции должны вернуть Collection
. В моем проекте их несколько, и я не хочу копировать и вставлять везде один и тот же код.
Обновлено: Пример:
Представьте себе case class Human(body: Body)
и class Body(limbs: List[Limbs])
У вас могут быть методы для body
, которые будут проходить через limbs
, и случаи, когда вы хотите иметь дело с телом в целом.
Как лучше всего это представить?
Редактировать:
Разве этот паттерн не является монадой или одним из тех функторов и т. д.?
Если я сделаю что-то вроде:
class MyCollection(item: Item*) {
def map(f: Item => Item): MyCollection
def flatMap(f: Item => MyCollection): MyCollection
def filter(p: Item => Boolean): MyCollection
}
Это сработает?
Что-то вроде: https://scastie.scala-lang.org/xn304lefRbO7vjwhopgE8g
нет ?
Мне нужны расширенные методы, связанные с типом Item
.
Прежде всего, я настоятельно рекомендую вам не думать о таких вещах, как Item ++ Collection
или Collection ++ Item
. Это не дает вам достаточного дополнительного удобства, чтобы гарантировать посягательство на хорошо понятное и общепринятое значение ++
. Если у вас есть какие-либо другие практические и «не антипаттерновые» потребности в обогащении для Item
, сообщите об этом, и мы можем помочь. Но не для этого, для меня это выглядит слишком антипаттерном.
Если вам просто нужны «расширенные методы», то рассматривали ли вы возможность использования implicit class
для добавления функциональности к существующим типам коллекций? Общий шаблон состоит в том, чтобы иметь функции, которые вы используете map
в коллекциях для создания новых коллекций, а не помещать функции в сами коллекции. Функции в коллекции должны относиться к самой коллекции, а не к ее содержимому.
Я чувствую, что есть случаи, когда это имеет смысл. Представьте себе case class Human(body: Body)
и class Body(limbs: List[Limbs])
, у вас могут быть методы для body
, которые будут проходить через limbs
, и случаи, когда вы хотите работать с body
как с единым целым. Как лучше всего это представить?
@SarveshKumarSingh Я отредактировал свой вопрос с другим оператором и добавил пример.
The end goal is to have a pair Item <-> Collection where the collection can only accept item of the right type and where the item can only be in this collection.
По-прежнему непонятно, для чего он нужен. Если вы пытаетесь реализовать какую-то линейную логику, тогда система типов Scala не подходит для этого. В противном случае я не понимаю, почему "товар может быть только в этой коллекции" - значимая цель. Если вам нужна только операция с |+|
, просто возьмите Monoid
. «Как моделировать человеческое тело» был бы слишком общим и слишком расплывчатым вопросом.
[2] Я не понимаю, как искусственное введение странных циклических взаимно рекурсивных зависимостей без очевидной причины могло бы сделать что-либо более понятным при любых обстоятельствах.
Я добавил scastie с образцом кода
Итак, какого положительного эффекта он дает, чего не дает case class Body(parts: List[BodyPart])
?
Я не знаю, это мой вопрос, ха-ха.
Что именно не так с обычными (не обернутыми) коллекциями, и Зачем вы пытаетесь делать то, что пытаетесь сделать? Для меня это проблема XY.