Squeak.ru - шаблоны программирования

Вывод типа все еще нуждается в улучшении, есть ли лучшее предложение для этого примера?

например в Clojure:

user=> (map #(* % 2) (concat [1.1 3] [5 7]))

(2.2 6 10 14)

но в Скала:

scala> List(1.1,3) ::: List(5, 7) map (_ * 2)

<console>:6: error: value * is not a member of AnyVal
       List(1.1,3) ::: List(5, 7) map (_ * 2)
                                       ^

Вот :::получить список типа List,упс тогда не удалось. Может ли какой-либо код более интуитивно понятен, как Clojure выше?

24.05.2010

  • Ваш вопрос будет немного легче читать, если вы воспользуетесь функциями форматирования кода Stack Overflow. 24.05.2010
  • Следует отметить, что Clojure динамически типизируется, что делает вывод типа ненужным или выполняется во время выполнения, в зависимости от вашей точки зрения. Одно из преимуществ полета без сетки. 24.05.2010
  • Это один из недостатков подтипов. В более гибкой системе типов, такой как Haskell, тип 3, например, не является ни Double, ни Int, а (Num t) => t, где Num — любое кольцо, подразумеваемое целыми числами. 24.05.2010
  • Чтобы продолжить точку зрения Апокалиспа, есть несколько обсуждений классов типов в Scala. На самом деле достаточно того, что вам следует поискать в Интернете класс типов Scala, если вы заинтересованы в методах. 24.05.2010

Ответы:


1

Вот вам отдельные списки:

scala> List(1.1,3)
res1: List[Double] = List(1.1, 3.0)

scala> List(5, 7)
res2: List[Int] = List(5, 7)

Вычисленная наименьшая верхняя граница (LUB) Double и Int, необходимая для захвата типа нового списка, включающего элементы обоих списков аргументов, переданных в :::, равна AnyVal. AnyVal включает Boolean, например, поэтому числовые операции не определены.

24.05.2010

2

Как уже сказал Рэндалл, общим супертипом Double и Int является AnyVal, что и выводится в данном случае. Единственный способ заставить ваш пример работать - добавить параметр типа во второй список:


scala> List[Double](1.1,3) ::: List(5, 7) map (_ * 2)
:6: error: value * is not a member of AnyVal
       List[Double](1.1,3) ::: List(5, 7) map (_ * 2)

scala> List(1.1,3) ::: List[Double](5, 7) map (_ * 2)
res: List[Double] = List(2.2, 6.0, 10.0, 14.0)

Я предполагаю, что в последнем случае применяется неявное преобразование из Int в Double. Однако я не уверен, почему это не применяется при добавлении параметра типа в первый список.

24.05.2010

3

Первый список имеет тип List[Double] из-за расширения литерального типа. Scala видит литералы и отмечает, что, хотя они и относятся к разным типам, их можно унифицировать, расширив некоторые из них. Если бы не было расширения типов, то был бы принят наиболее распространенный суперкласс AnyVal.

List(1.1 /* Double literal */), 3 /* Int literal */)

Второй список явно List[Int], хотя явный вызов Double приведет к расширению типа литералов.

List(5 /* Int literal */, 7 /* Int literal */)

Теперь важно отметить, что расширение типов происходит во время компиляции. Скомпилированный код не будет содержать Int 3, только Double 3.0. Однако после того, как список был создан, расширить тип невозможно, потому что сохраненные объекты на самом деле разные.

Итак, как только вы соедините два списка, результирующий тип будет суперклассом Double и Int. А именно AnyVal. Однако в результате взаимодействия с Java AnyVal не может содержать каких-либо полезных методов (таких как числовые операторы).

Мне интересно, что Clojure делает внутри. Преобразует ли он целые числа в двойные числа при конкатенации? Или он хранит все как Object (как Scala), но имеет более умные математические операторы?

24.05.2010

4

Я вижу два способа заставить это работать - фигурные скобки для второй части

scala> List (1.1, 3) ::: (List (5, 7) map (_ * 2))
res6: List[AnyVal] = List(1.1, 3, 10, 14)

или явные двойники везде:

scala> List (1.1, 3.) ::: List (5., 7.) map (_ * 2)  
res9: List[Double] = List(2.2, 6.0, 10.0, 14.0)

что, конечно, семантически отличается.

24.05.2010

5

Почему бы не просто,

(List(1.1,3) ::: List(5, 7)).asInstanceOf[List[Double]] map (_ * 2)

?

25.05.2010
Новые материалы

Угловая структура архитектуры
Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

«Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

Создайте API с помощью Python FastAPI
Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

Веселье с прокси-сервером JavaScript
Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...