metaclass: (Default)
[personal profile] metaclass
Читаю про тайпклассы и имплиситы в скале:
http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

Не совсем понимаю один момент. В статье мы вызываем функцию (printLabel) для объекта, конкретная реализация которой ищется компилятором в виде имплисита в скале или в реализации тайпкласса в хаскеле. Но это все, условно говоря "раннее связывание", на этапе компиляции.

А вот если мы ходим сделать универсальную функцию вроде "на входе список объектов, на выходе - список строковых представлений", причем, во-первых, объекты сами по себе ни от чего типа "Object с методом printLabel" не наследуются и интерфейсов соответствующих не реализуют (ну, скажем объект - это Anemic Data Model, тупая запись с полями и прочее POCO/POJO вообще), а printLabel реализована вот как в статье - в отдельном связанном объекте-адаптере - то как, во-первых, мы запишем тип такой функции, а во вторых - как мы ее реализуем?

В хаскеле можно было намутить чего-то с соответствующим тайпклассом и экзистенциальными типами ("список любых объектов, у которых есть тайпкласс LabelMaker"). А с трейтами и прочей скалой чего можно сделать?

На мирных языках типа жабе, C# или дельфей - придется вообще делать диспетчеризацию по типу и глобальный словарь вида "тип->функция", регистрировать в нем функции печати(в F# pretty printer вроде так и реализован), но это никаких статических гарантий правильности вообще не даст. Впрочем, в стиле "хуяк-хуяк и в продакшен" это не проблема - для всех типов, где мы не нашли функцию - выводим надпись "ИмяТипа_ОбратитесьВОбслуживающуюОрганизациюЕслиВыВидитеЭтоИЗаплатите100500ДенегЗаОбслуживание" и все, ничего не упадет, кому надо - обратятся.

Date: 2013-10-11 07:11 am (UTC)
From: [identity profile] potan.livejournal.com
В хаскеле "с соответствующим тайпклассом и экзистенциальными типами" не все так просто. Если написать f :: forall a . Show a => [a] -> String, то получится функция, которая принимает список элемента типа, принадлежащего Show, а не списка любой херни, для которого есть инстанс Show.
В скале придется делать аналогично и implicits помещать в структуре данных вместе со значением, которое им будет обрабатываться. Получается не столь элегантно, но и проблема, в общем то, надуманная.

Date: 2013-10-11 07:49 am (UTC)
From: [identity profile] jakobz.livejournal.com
Мне проще было так понять: эти все экзистенциальные типы работают через передачу хаскельного аналога vtable в рантайме. В твоем случае ты один "vtable" принимаешь на вход функции, т.е. вот это вот Show a => - это будет откомпилено в доп-параметр с лукапом функций. В этом примере тип всех элементов списка будет одинаковым.

{-# LANGUAGE ExistentialQuantification #-}

module Main where

--Чтобы тип элементов списка сделать разным - надо тип и vtable сначала слепить вместе:

data Showable = forall a . Show a => Showable a

-- Потом в список напихивать инстансы именно этой обертки (в этот момент мы как раз берем этот vtable и слепляем с инстансом):

myList = [Showable 1, Showable "test"]

-- А потом уже писать функции типа [Showable] -> String:

test :: [Showable] -> String
test = concatMap (\(Showable item) -> show item)

main = print $ test myList

Date: 2013-10-11 07:51 am (UTC)
From: [identity profile] xeno-by.livejournal.com
А можно как-нибудь обойтись без модификации myList? Хотелось бы чтобы можно было писать [1, "test"], если такое возможно.

Date: 2013-10-11 08:10 am (UTC)
From: [identity profile] jakobz.livejournal.com
Не, так вроде не выйдет. Мне тоже так сначала хотелось и казалось что этот подход с обертками - дюже кривой. Но на практике оно наоборот кажется очень прагматичным решением.

Во-первых ты не таскаешь vtable повсюду. В большинстве случаев экзистенциальные типы не нужны, нужный vtable выпаливается при компиляции, и может даже это оптимизируется. В отличии от дотнетов и яв, где у тебя каждый интерфейс - это плюс один указатель к каждому объекту в любом раскладе.

Во-вторых обертка обычно не такая прям и простая. И вообще эта гибкость с тем куда и зачем пихать vtable - она весьма в тему.

Date: 2013-10-11 08:11 am (UTC)
From: [identity profile] xeno-by.livejournal.com
Спасибо!

Date: 2013-10-11 08:13 am (UTC)
From: [identity profile] potan.livejournal.com
Можно. Но не на Haskell.
На питончике - запросто.

Date: 2013-10-11 07:55 am (UTC)
From: [identity profile] nealar.livejournal.com
Да, надо a заворачивать в экзистенциал, а потом уже сувать в список.

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 27th, 2025 08:04 pm
Powered by Dreamwidth Studios