Введите параметр в контексте, который вызывает некоторую двусмысленность

У меня есть следующая ошибка для cadr1 ниже, что имеет смысл

Не удалось вывести (BoolEq n ('Succ ('Succ n'0)) ~ 'True)

из контекста (BoolEq n ('Succ ('Succ n')) ~ 'True)

Переменная типа «n'0» неоднозначна

{-# LANGUAGE DataKinds      #-}
{-# LANGUAGE GADTs          #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes     #-}
{-# LANGUAGE TypeFamilies   #-}

module DecidablePropositionalEquality where


data Nat = Zero | Succ Nat

data Vec :: * -> Nat -> * where
  VNil  :: Vec a Zero
  VCons :: a -> Vec a n -> Vec a (Succ n)

type family Greater (a:: Nat) (b:: Nat) :: Bool where
  Greater Zero Zero = True
  Greater Zero (Succ x) = False
  Greater (Succ x) Zero = True
  Greater (Succ a) (Succ b) = Greater a b

op :: forall a n n'. (Greater n (Succ (Succ n')) ~ True) => Vec a n -> a 
op v = undefined

Я не использую n' на сайте определения, так что это неоднозначно.

Могу ли я в любом случае дать экзистенциальную количественную оценку этому n', чтобы ghc не пытался присвоить его какому-либо типу и потерпел неудачу, поскольку ничто не связывает его ни с чем?

В более общем смысле, как контролировать область действия этих переменных типа?

изменить: изменено для удаления семейства логических типов.


person nicolas    schedule 30.06.2017    source источник
comment
Почему не cadr1 :: forall a n'. Vec a (Succ (Succ n')) -> a ?   -  person chi    schedule 30.06.2017
comment
Звучит как отличное решение для этого конкретного случая. но мне интересно, есть ли способы удалить/охватить (через количественную оценку) эти имена. Здесь я хотел бы, чтобы n' был привязан к этому коду. и так как я не собираюсь ничего из него использовать, само его существование прекрасно. и это не должно быть «двусмысленным», если GHC не пытается присвоить его чему-то, выходящему за рамки его предполагаемой области применения.   -  person nicolas    schedule 30.06.2017
comment
@chi, я изменю вопрос, он ... двусмысленный :)   -  person nicolas    schedule 30.06.2017
comment
Семейства логических типов являются наиболее общий антишаблон Я вижу в Stack Overflow вопросы о зависимо типизированном Haskell. n ~ Succ (Succ n') — это совершенно хорошее ограничение, и оно не является двусмысленным.   -  person Benjamin Hodgson♦    schedule 30.06.2017
comment
@BenjaminHodgson :)) хорошо, это вспышка. у вас, кажется, есть верная точка зрения для случая BoolEq, я пытался придумать что-то простое, где у нас действительно есть двусмысленность, не пытаясь найти способы ее избежать.   -  person nicolas    schedule 30.06.2017
comment
@николас, я вижу. Общее средство от этого — использовать лучший дизайн, хотя это не особенно полезный совет, ха-ха. Лучший дизайн, о котором идет речь, конечно, зависит от ситуации. Возможно, мы смогли бы дать вам больше советов, если бы код в вашем вопросе был более репрезентативным для реального кода, в котором вы видите эту проблему?   -  person Benjamin Hodgson♦    schedule 30.06.2017
comment
@BenjaminHodgson Спасибо. Мне было больше любопытно, как такие имена обрабатываются в Haskell в настоящее время. в частности, как контролировать их объем. но я предполагаю, что ваш ответ на использование лучшего дизайна, тем не менее, говорит, как прагма AllowAmbiguousTypes, или прибегает к синглтонам (афаик)   -  person nicolas    schedule 30.06.2017
comment
Даже если вы включите AllowAmbiguousTypes, параметр типа n' совершенно бесполезен — типы стираются во время выполнения, поэтому нет абсолютно никакой возможности выполнять вычисления с ним внутри тела op. Вам нужно ограничение класса типа для n', или синглтон, хранящий его значение, или что-то в этом роде. Вы, вероятно, думаете о чем-то вроде вызова пользователя, например. op @5 и получить параметрическую функцию, которая всегда выдает вектор наименьшей длины 7; но с данным типом вы просто не смогли бы реализовать такую ​​функцию.   -  person user2407038    schedule 01.07.2017