haskell - 为复杂类型创建任意实例
问题描述
我正在尝试使用 QuickCheck 检查我的代码,因此我需要Arbitrary
为我的类型创建实例。一种data Schedule
是复杂的,不知道如何正确对待。三个实例(for Date
, Activity
, TimeStart
)工作正常。但是最后一个实例 (for Schedule
) 不正确,我寻求帮助来修复它。
data Schedule = Schedule [(Date,[Activity])]
data Date = Date Year Month Day
data Activity = Activity (ActivityName,TimeStart)
data TimeStart = TimeStart Hour Minute
type Year = Integer
type Month = Integer
type Day = Integer
type ActivityName = String
type Hour = Integer
type Minute = Integer
instance Arbitrary Date where
arbitrary = do
year <- choose (2000, 2050)
month <- choose (1, 12)
day <- choose (1, 28)
return $ Date year month day
instance Arbitrary Activity where
arbitrary = do
size <- choose (5, 15 :: Integer)
activityName <- sequence [elements ['a'..'z'] | _ <- [1..size]]
timeStart <- arbitrary
return $ Activity (activityName, timeStart)
instance Arbitrary TimeStart where
arbitrary = do
hour <- choose (1, 24)
minute <- choose (1, 60)
return $ TimeStart hour minute
instance Arbitrary Schedule where
arbitrary = do
size <- choose (5, 50 :: Integer)
schedule <- sequence [(arbitrary, arbitraryActivity) | _ <- [1..size]]
return $ Schedule schedule where
arbitraryActivity = do
size <- choose (5, 50 :: Integer)
activityName <- sequence [arbitrary | _ <- [1..size]]
return $ ActivityName activityname
第一个错误就在这一行:schedule <- sequence [(arbitrary, arbitraryActivity) | _ <- [1..size]]
Expected type: Gen [Gen b0] Actual type: (Gen a0, [Gen b0])
但是如何[(x,y)]
正确地为这样的结构做一个任意的?
第二个错误在最后一行:return $ ActivityName activityname
Data constructor not in scope: ActivityName
是否不允许where
像我一样在 do-notation 中使用?
解决方案
当您已经拥有Arbitrary
复杂类型的所有组成类型(在本例Date
中为Activity
、 等)的实例时,您不必做太多事情。
Arbitrary
由于列表、元组等的内置实例,您可以Arbitrary
像这样简单地定义组合实例:
instance Arbitrary Schedule where
arbitrary = Schedule <$> arbitrary
编译器查看Schedule
类型为 的数据构造函数[(Date, [Activity])] -> Schedule
。然后,它推断右手arbitrary
必须具有类型Gen (Date, [Activity])
,即元组。是否Arbitrary
存在实例(a, b)
?
是的,它确实:(Arbitrary a, Arbitrary b) => Arbitrary (a, b)
. 它存在 ifa
是一个Arbitrary
实例,如果b
是。
在本例中a ~ Date
,您已经为此定义了一个自定义实例。第二个元组元素有点复杂,因为它是b ~ [Activity]
. 有没有Arbitrary
实例[Activity]
?
是的,再次内置:Arbitrary a => Arbitrary [a]
. 如果元素类型具有实例,则列表具有Arbitrary
实例,并且同样存在用于 的自定义实例Activity
。
看起来您好像在明确尝试限制生成值的大小。您可以使用resize函数,而不是显式执行此操作。
推荐阅读
- python - 使用滑块小部件过滤和更新交互式散景可视化
- c# - 反序列化对象数组:无法将 JSON 值转换为 System.String[]
- hyperledger-fabric - 尝试更新 Anchor Peer 时出现错误 SERVICE_UNAVILABLE
- python - 编写代码以在对象上生成随机颜色
- c++ - 如何从文件中获取字体名称?
- django - Django Rest:为什么访问被拒绝,尽管 AccessAny 设置为权限?
- date - 从日期字段中选择日期时出现 ExtJS 错误
- asp.net-core - 使用 AspNet Core 和 API Gateway 的 Lambda 函数的 Cors 错误
- c++ - 在 Visual Studio Code 中使用 C++ 读取 csv 文件并将数据存储在数组中
- javascript - 我如何在反应中使用 MS 图形 API?