Скажем, я хотел бы построить подтипы, удовлетворяющие определенным инвариантам, без помощи внешних инструментов, таких как LiquidHaskell (в идеале я хочу сделать это даже без типов). Какой самый элегантный способ сделать это? До сих пор я попытался следующие:Проверка на уровне уровня
class Validated a where
type Underlying a
validate :: Underlying a -> Bool
construct :: Underlying a -> a
use :: a -> Underlying a
makeValidated :: Validated a => Underlying a -> Maybe a
makeValidated u = if validate u
then Just (construct u)
else Nothing
newtype Name = Name String
instance Validated Name where
type Underlying Name = String
validate str = and [ isUppercase (str !! 0)
, all isLetter str ]
construct = Name
use (Name str) = str
Я полагаю, что если я не экспортировать «Name» конструктор из модуля, у меня будет рабочее решение, потому что единственный способ построить элемент типа будет через makeValidated function.
Однако компилятор жалуется, как например:
Could not deduce (Underlying a0 ~ Underlying a)
from the context (Validated a)
bound by the type signature for
makeValidated :: Validated a => Underlying a -> Maybe a
at validated.hs:11:18-55
NB: `Underlying' is a type function, and may not be injective
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
In the first argument of `validate', namely `u'
In the expression: validate u
In the expression:
if validate u then Just (construct u) else Nothing
Как я могу это исправить?
Я попытался модифицировать свой код следующим образом, но я получаю то же сообщение об ошибке. Что я делаю не так? 'Proxy данные а = Proxy' класса' '' Удостоверенная where' 'типа Базового a' ' проверки :: Proxy а -> В основе а -> Bool' 'построить :: В основе а -> а ' ' use :: a -> Underlying a' '' 'makeValidated :: Validated a => Underlying a -> Maybe a' ' makeValidated u = if validate (Proxy :: Proxy a) u' 'then Just (construct u) ' ' else Nothing' – NioBium
@NioBium Вам нужно использовать 'makeValidated :: forall a. Validated a => ... 'и включите расширение языка ScopedTypeVariables. Вероятно, лучшим выбором может быть удаление 'validate, construct' из вашего класса и добавление' makeValidated' вместо этого в класс. – chi