Семейства типов не могут возвращать тип RankN - обходные пути или альтернативы?
Я играю с расширяемой библиотекой записей и хочу написать функцию field
который может работать как Lens
или Traversal
в зависимости от того, Symbol
Ключ находится в списке ключей. Типовое семейство дается:
type family LensOrTraversal key keys s t a b where
LensOrTraversal key '[] s t a b =
Traversal s t a b
LensOrTraversal key (key =: val ': xs) s t a b =
Lens s t a b
LensOrTraversal key (foo =: bar ': xs) s t a b =
LensOrTraversal key xs s t a b
Этот код дает мне ошибку:
/home/matt/Projects/hash-rekt/src/Data/HashRecord/Internal.hs:433:5:
error:
• Illegal polymorphic type: Traversal s t a b
• In the equations for closed type family ‘LensOrTraversal’
In the type family declaration for ‘LensOrTraversal’
В идеале я хотел бы иметь возможность повторно использовать field
название для линз и обходов, так как это позволит вам написать
>>> let testMap = empty & field @"foo" .~ 'a'
>>> :t testMap
HashRecord '["foo" =: Char]
>>> testMap ^. field @"foo"
'a'
>>> testMap ^. field @"bar"
Type error
>>> testMap ^? field @"bar"
Nothing
что следует за общим lens
идиомы. Я могу предоставить fieldTraversal
функция, которая делает то, что я хочу, но я бы предпочел перегрузить имя field
если возможно. Как бы вы обошли это ограничение семейства типов?
1 ответ
Объектив уже пройден, только его квантификатор Rank2 не использует полное ограничение (оно просто требует Functor
не Applicative
).
type Lens s t a b = ∀ f . Functor f => (a -> f b) -> s -> f t
type Traversal s t a b = ∀ f . Applicative f => (a -> f b) -> s -> f t
Именно на уровне этого ограничения вы должны представить свое семейство типов:
import GHC.Exts (Constraint)
type family FieldOpticConstraint key keys :: (* -> *) -> Constraint where
FieldOpticConstraint key '[] = Applicative
FieldOpticConstraint key (key =: val ': xs) = Functor
FieldOpticConstraint key (_ ': xs) = FieldOpticConstraint key xs
затем field
не должен давать LensOrTraversal
, но всегда пользовательская сигнатура Rank2 с ограничением, определяемым семейством типов.