重构当前类型时遇到问题(可能 GADT/Type 家族相关)
Trouble refactoring current types(possibly GADT/Type Families related)
我有这样的类型:
-- 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 的 FromJSON
实例以及其他功能可以很容易地演示我所追求的属性。
需要前 3 个属性来生成正确的测试数据,第 4 个属性需要
实施业务逻辑。
我希望能够:
make 所有代码类型的任意实例如
instance Arbitrary ICode where
arbitrary = ...
-- same with RCode and DCode
创建 Arbitrary
类型的实例,例如 Location1 ICode
(它明显不同于当前的实现,这是我要修复的),它描述了位置类型的精确组合和代码类型。 Location1 ICode
只能包含 ICode
个可能值的子集,因此我必须确保这一点。
生成所有可能类型的 FromJSON
个实例,类似于:
instance FromJSON (Location a) where
parseJSON = ...
需要根据某些 json 对象的值反序列化它们。
有些功能只能在一种位置类型上工作。这在当前的实现中非常不方便,因为我必须使用不完整的函数或不正确的 return 类型,例如 Maybe
。我希望能够做类似的事情:
location1IncludedInArbitraryLocation :: LocType1 -> Location a -> Bool
location1IncludedInArbitraryLocation l = ...
我相信解决方案就在 GADTs/Data 家庭领域的某个地方,但我对这种打字不是很流利。如果有多种方法可以解决此问题,那么稍后 typecheck/work 哪种方法更容易?
3 和 4 似乎不兼容。这听起来像是一种 "fallback" 机制:如果没有更具体的实例可用,则使用此实例。您可以使用 OverlappingInstances 获得此功能,但我似乎总是 运行 遇到麻烦。值得一试,我想。
至于你剩下的问题,你似乎希望 Location
成为 GADT。
data LocType = Type1 | Type2 | Type3 | Type4
data Location :: LocType -> * where
LocType1 :: ICode -> Location Type1
LocType2 :: ICode -> Location Type2
LocType3 :: RCode -> Location Type3
LocType4 :: DCode -> Location Type4
那么你可以轻松做到:
location1IncludedInArbitraryLocation :: Location Type1 -> Location t -> Bool
location1IncludedInArbitraryLocation (LocType1 icode) l = ...
这里不需要定义其他情况,因为没有其他构造函数是良类型的。
我希望这能让你开始玩。
(需要 DataKinds
、KindSignatures
、GADTs
)
我有这样的类型:
-- 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 的 FromJSON
实例以及其他功能可以很容易地演示我所追求的属性。
需要前 3 个属性来生成正确的测试数据,第 4 个属性需要
实施业务逻辑。
我希望能够:
make 所有代码类型的任意实例如
instance Arbitrary ICode where arbitrary = ... -- same with RCode and DCode
创建
Arbitrary
类型的实例,例如Location1 ICode
(它明显不同于当前的实现,这是我要修复的),它描述了位置类型的精确组合和代码类型。Location1 ICode
只能包含ICode
个可能值的子集,因此我必须确保这一点。生成所有可能类型的
FromJSON
个实例,类似于:instance FromJSON (Location a) where parseJSON = ...
需要根据某些 json 对象的值反序列化它们。
有些功能只能在一种位置类型上工作。这在当前的实现中非常不方便,因为我必须使用不完整的函数或不正确的 return 类型,例如
Maybe
。我希望能够做类似的事情:location1IncludedInArbitraryLocation :: LocType1 -> Location a -> Bool location1IncludedInArbitraryLocation l = ...
我相信解决方案就在 GADTs/Data 家庭领域的某个地方,但我对这种打字不是很流利。如果有多种方法可以解决此问题,那么稍后 typecheck/work 哪种方法更容易?
3 和 4 似乎不兼容。这听起来像是一种 "fallback" 机制:如果没有更具体的实例可用,则使用此实例。您可以使用 OverlappingInstances 获得此功能,但我似乎总是 运行 遇到麻烦。值得一试,我想。
至于你剩下的问题,你似乎希望 Location
成为 GADT。
data LocType = Type1 | Type2 | Type3 | Type4
data Location :: LocType -> * where
LocType1 :: ICode -> Location Type1
LocType2 :: ICode -> Location Type2
LocType3 :: RCode -> Location Type3
LocType4 :: DCode -> Location Type4
那么你可以轻松做到:
location1IncludedInArbitraryLocation :: Location Type1 -> Location t -> Bool
location1IncludedInArbitraryLocation (LocType1 icode) l = ...
这里不需要定义其他情况,因为没有其他构造函数是良类型的。
我希望这能让你开始玩。
(需要 DataKinds
、KindSignatures
、GADTs
)