Допустим, мы получили следующее:сдерживающими экземпляры
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilyDependencies #-}
type family CategoryLikeT p_a_b = t | t -> p_a_b
type IsCategoryLike p t a b = (t ~ CategoryLikeT (p, a, b))
class CategoryLike p where
(>>>) ::
(
IsCategoryLike p t1 a b,
IsCategoryLike p t2 b c,
IsCategoryLike p t3 a c
) => t1 -> t2 -> t3
Мы находим, что это нормально компилируется:
f ::
(
CategoryLike p,
IsCategoryLike p t1 a b,
IsCategoryLike p t2 b c,
IsCategoryLike p t3 c d,
IsCategoryLike p t4 a d
) => t1 -> t2 -> t3 -> t4
f x y z = x >>> y >>> z
Но мы не определили экземпляры еще. Позволяет сделать:
data BasicFunction
type instance CategoryLikeT (BasicFunction, a, b) = a -> b
instance CategoryLike BasicFunction where
(>>>) = flip (.)
, но и «Ints» при сложении является своим родом категории, как, если мы предположим, «а» и «б» являются как Void
, например: BasicInt данные типа экземпляра CategoryLikeT (BasicInt, Пустота, Пустота) = Int
instance CategoryLike BasicFunction where
(>>>) = (+)
конечно выше не работает, потому что нет никаких ограничений на «а» или «б» в определении экземпляра, так что нет гарантирую >>>
получает все-таки типа, следовательно, (+)
недостаточно общего. Так что я считал делает следующее:
Во-первых, добавление типа ограничений:
type family CategoryConstraints p t a b
И затем добавляет к определению IsCategoryLike
как следующее:
type IsCategoryLike p t a b =
(t ~ CategoryLikeT (p, a, b), CategoryConstraints p t)
Затем мы можем добавить следующее ограничение:
type instance CategoryConstraints BasicInt t = (t ~ Int)
Но теперь у нас есть проблема , не f
больше не работает, что дает эту ошибку:
Could not deduce: CategoryConstraints p (CategoryLikeT (p, a, c)))
Мы можем исправить это двумя способами:
Во-первых, путем добавления IsCategoryLike p t5 a c
к ограничениям в f
. Но это может стать очень грязным для более сложных функций, вам придется добавить ограничение для каждой операции. Также тривиальные изменения, например изменение до x >>> (y >>> z)
, требуют изменения подписи, что не требовалось, если у вас не было ограничений.
Альтернативно, подпись типа может быть полностью опущена, или могут использоваться частичные сигнатуры.
Тем не менее, я хотел бы сохранить подписи полного типа, не увеличиваясь и не выдерживая сложностей. Могут ли люди предлагать альтернативные подходы?
Ключевой вопрос: можете ли вы написать 'f' с типом? – Clinton
@Clinton Все еще не отличная подпись, но немного лучше. По крайней мере, его можно использовать элегантно с применением видимого типа – Alec