Я получил типов, как это:Trouble рефакторинга текущих типов (возможно GADT/типа семей, связанный)
-- There are codes
newtype ICode = ICode { fromICode :: String }
newtype RCode = RCode { fromRCode :: String }
data DCode = DCode1 | DCode2 | DCode3
-- There are locations described by type and code.
-- Current implementation looks like this:
data Location = LocType1 ICode
| LocType2 ICode
| LocType3 RCode
| LocType4 DCode
Я хотел бы, чтобы реорганизовать эти типы для решения некоторых проблем, которые присутствуют в текущей реализации.
Это действительно легко продемонстрировать свойства, которые я получаю после QuickCheck Arbitrary
и Aeson's FromJSON
экземпляров и еще одна функция. Первые 3 свойства необходимы для генерации правильных тестовых данных, а 4-й - реализуют бизнес-логику.
Я хотел бы быть в состоянии:
делают произвольные экземпляры всех типов кодов, таких как
instance Arbitrary ICode where arbitrary = ... -- same with RCode and DCode
Arbitrary
делают экземпляры типов, какLocation1 ICode
(Это явно отличается от тока и это то, что я пытаюсь исправить), которые описывают точную комбинацию типа местоположения и типа кода.Location1 ICode
может содержать только подмножествоICode
возможных значений, поэтому я должен убедиться в этом.сделать
FromJSON
экземпляров всех возможных типов, что-то в линиях:instance FromJSON (Location a) where parseJSON = ...
Это необходимо для десериализации некоторых объектов JSon в зависимости от их значений.
Некоторые функции должны работать только с одним типом местоположения. Это довольно неудобно в текущей реализации, потому что я должен использовать либо неполные функции, либо не совсем правильные типы возврата, такие как
Maybe
. Я хотел бы быть в состоянии сделать что-то вроде:location1IncludedInArbitraryLocation :: LocType1 -> Location a -> Bool location1IncludedInArbitraryLocation l = ...
Я считаю, что решение лежит где-то в GADTs/территориях Families данных, но я не очень свободно с таким типом-фу. Если возможно несколько способов решения этой проблемы, какой из них легче будет выполнять с помощью метода typecheck/work?
вы пробовали * типы фантомные * в раздел 'ICode' и т.д.? – phadej
@phadej Я подумал об этом, но еще не пробовал. Кажется, что типы фантомов помогут с произвольными экземплярами, но не помогут с номером свойства 4. – dredozubov
Для 4. Я бы предложил создать собственный тип 'newtype LocTypeOne = LocTypeOne ICode' и' LocType1 LocTypeOne' внутри 'LocType' ADT , Затем добавьте функцию «явного принуждения» LocTypeOne -> LocType', и все готово. – phadej