Пост про дизайн.

Jun 10, 2010 22:34

Большое спасибо archimag, откликнувшегося на мою предложение написать пост ( Read more... )

блоги, дизайн, ЖЖ, языки программирования, Хаскель

Leave a comment

lomeo June 10 2010, 21:54:01 UTC
Что-то я не понял. А что будет, если мы просто не укажем StackSlot для Maybe? Разве не то же самое?

Reply

thesz June 10 2010, 22:10:55 UTC
Почти то же самое, только кому-либо в голову может придти его указать.

Reply

lomeo June 11 2010, 04:20:25 UTC
Нужны sealed классы. Я подума.

Reply

thesz June 11 2010, 08:45:58 UTC
Можно и по другому поступить:
class StackSlots a size | a -> size
instance StackSlots Char (S Z)
instance StackSlots Int (S Z)
instance StackSlots a size => StackSlots (Maybe a) (S size)
class StackSlots a (S Z) => StackSlot a

Это даже логичней.

Reply

lomeo June 11 2010, 10:21:43 UTC
Да, как то так...

{-# LANGUAGE TypeFamilies, EmptyDataDecls #-}

data Yes
data No

type family Fit a :: *

type instance Fit Char = Yes
type instance Fit Int = Yes
type instance Fit (Maybe a) = No

test :: (Fit a ~ Yes) => a -> a
test = id

Кстати, есть такая прикольная практика - partial signature, может знаешь, а если нет, то может окажется полезным. Смысл такой - тебе не хочется выписывать весь тип самому, но некоторые ограничения ты прописать хочешь. Например, для функции test ты хочешь прописать ограничение Fit a ~ Yes

-- определяем ограничение, которое мы будем добавлять к нужным нам функциям (test, dup, over...)
fitParam :: (Fit a ~ Yes) => a -> b
fitParam = undefined

-- добавляем ограничение
test a | False = fitParam a
-- основная реализация
test a = a

Это меня nealar в своё время натолкнул
http://okmij.org/ftp/Haskell/partial-signatures.lhs

Reply

thesz June 11 2010, 20:43:58 UTC
Про частичные типы я знаю, я их рассматриваю, как "тактики", так сказать. ;)

Fit a = Yes/No хуже учёта размеров. Размер можно потом использовать в своих целях, Yes/No слишком ограничены.

Reply

lomeo June 11 2010, 21:15:04 UTC
Да это иллюстрация же. Я хотел показать, что type families выразительнее fundeps. Ну, и fundeps не кошерно же :)

Reply

thesz June 11 2010, 21:19:46 UTC
Да что-то у меня не осталось такого впечатления, что они выразительней.

Запиши равенство типов на type families. Запиши HList lookup.

У меня не получается.

Reply

lomeo June 12 2010, 05:58:37 UTC
Выразительнее, потому что они предназначены для подобных выражений мысли. Всё таки в подобном использовании классов чувствуется, что этот инструмент совсем для другого задумывался.

Равенство типов - это вот это?

type family Equal a
type instance Equal a = a

test :: (Equal a ~ b) => a -> b -> (a, b)
test = (,)

Что такое HList lookup посмотрю сначала, потом отвечу.

Reply

lomeo June 12 2010, 06:18:58 UTC
Посмотрел, с первого раза кажется, что hlist lookup не запишется, потому что нельзя навешивать контексты на type instances. Когда они уже это добавят!

Но я бы это делал на HList, который имеет только Eq элементы, и использовал cast и (==). Так проще всего, IMHO. А вообще надо подумать, но чуть позже :)

Reply

thesz June 12 2010, 08:07:11 UTC
lookup на HList интересен только в момент компиляции, потому, что далее мы работаем с полученным типом. ;)

Так что вот тебе и ограничения в выразительности.

Reply

lomeo June 12 2010, 11:21:21 UTC
Э, погоди! Если это лукап по типу, а не по ключу, то проблема именно в недоразвитости type family (нельзя добавить контекст). Ну нет у open functions возможности FlexibleTypeInstances и OverlappedTypeInstances :)

Поэтому классы вынужденная мера и здесь уже можно использовать не fundeps, а associated types.

Reply

lomeo June 11 2010, 10:35:16 UTC
Блин! sealed классы - это же GADT!

Реализация, правда, вывернется, но над этим тоже можно подумать. Кстати, тут достаточно просто ADT.

Reply

nealar June 11 2010, 10:57:11 UTC
Это как? Конструкторы возвращают словарь класса, и он для каждого типа аргумента получается разный?

Reply

lomeo June 11 2010, 11:06:15 UTC
Да, я наврал, ADT недостаточно.

Я имею в виду как-то так

{-# LANGUAGE GADTs #-}

data Fit a where
IntFit :: Int -> Fit Int
CharFit :: Char -> Fit Char

test :: Fit a -> a
test (IntFit x) = x
test (CharFit x) = x

Reply

ext_72902 June 11 2010, 11:34:41 UTC
Ну, можно и по-обычному:
class Fit a where fit :: forall p. p Int -> p Char -> p a

Reply


Leave a comment

Up