Как я могу сделать переключение уровня `(,)`? - PullRequest
0 голосов
/ 07 декабря 2018

Я хотел расширить идею fst и snd для типов классов.Итак, я написал классы типов

class Fstable f where
   fst' :: f a -> a

class Sndable f where
   snd' :: f a -> a

Было достаточно легко написать экземпляр для Sndable, просто следующее

instance Sndable ((,) a) where
  snd' (a, b) = b

Однако экземпляр для Fstable не так прост,Теперь я бы очень хотел использовать flip на (,) для создания * -> *, который я хочу.Но на уровне типов переворачивания не происходит, поэтому мне придется самому создать или сделать * -> *, который я хочу сам.

Я ничего не делал на уровне типов за пару месяцев, но помнюодин из способов сделать функции уровня типа - это использование FunctionalDependencies.Я могу сделать бросок (,) достаточно легко:

{-# Language MultiParamTypeClases, FunctionalDependcies, FlexibleInstances #-}

class BackTuple a b c | a b -> c

instance BackTuple a b (b, a)

Но BackTuple имеет вид * -> * -> * -> Constraint вместо * -> * -> *, который я хочу.

Итак, я попытался использоватьсиноним типа

{-# Language TypeSynonymInstances #-}

type W a b = (b, a)

instance Fstable (W a) where
  fst' (a, b) = a

Но я не могу карри, поэтому W a жалуется на то, что ему не W предоставляется неверное количество аргументов.Я чувствую, что, возможно, семейство типов могло бы это исправить, но я не знаю, с чего начать.

Я пытался создать флип, но я действительно не знал, с чего начать.

Как мне сделать бросок (,)?

1 Ответ

0 голосов
/ 07 декабря 2018

Одним из вариантов будет использование простого старого класса с простым родом, а не класса с более высоким родом.Например:

class Fstable tuple fst | tuple -> fst where fst' :: tuple -> fst
class Sndable tuple snd | tuple -> snd where snd' :: tuple -> snd

instance Fstable (a,b) a where fst' = fst
instance Sndable (a,b) b where snd' = snd

Аналогичные определения могут быть сделаны с семействами типов, если вы предпочитаете, конечно:

class Fstable tuple where type Fst tuple; fst' :: tuple -> Fst tuple
class Sndable tuple where type Snd tuple; snd' :: tuple -> Snd tuple

instance Fstable (a,b) where type Fst (a,b) = a; fst' = fst
instance Sndable (a,b) where type Snd (a,b) = b; snd' = snd

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

newtype Flip f b a = Flip (f a b)
instance Fstable (Flip (,) b) where
    fst' (Flip (a,b)) = a
...