如何使用Haskell类型重载方法

如何使用Haskell类型重载方法,haskell,Haskell,我正在做一个小项目,我试图学习Haskell并制定一个计划来帮助计划学生的时间表。我有以下几种: data Course = { id :: Int, title :: String } deriving (Eq, Show) data Req = Single Course | Any [Req] | All [Req] deriving Show 现在我想写一个方法: satisfies :: [Course] -> Req -> Bo

我正在做一个小项目,我试图学习Haskell并制定一个计划来帮助计划学生的时间表。我有以下几种:

data Course =
    { id :: Int, title :: String }
    deriving (Eq, Show)

data Req = Single Course
    | Any [Req]
    | All [Req]
    deriving Show
现在我想写一个方法:

satisfies :: [Course] -> Req -> Bool

但是我不知道应该如何使用关于Req的信息来重载函数。我应该如何继续?

好的,我假设你想要的是接受
Req
,然后根据它,决定给定的
课程列表是否满足它

第二,我会做一个改变,让这更不痛苦

Req = ... Any [Courses] | All [Courses] ...
而不是
[Req]
s,因为实际上,对于这个函数来说,处理任意嵌套的需求有点不可靠和怪异

为此,我们将进行一些模式匹配:

satisfies :: [Courses] -> Req -> Bool
satisfies courses (Single course) = undefined
satisfies courses (Any reqs)      = undefined
satisfies courses (All reqs)      = undefined
好的,现在我们有三个问题

首先,我们如何检查列表是否包含元素?我会让你知道怎么做,假设你知道一个函数
elem

satisfies courses (Single course) = course `elem` courses
第二,我们如何检查两个列表是否相交?假设函数是
inter

satisfies courses (Any reqs)      = courses `inter` reqs
最后,我们如何检查一个列表是否包含另一个?称之为
contains

satisfies courses (All reqs0)      = courses `contains` reqs
现在这是处理ADT的一种非常常见的方法。将它们分开,进行个案分析。

首先,一些打字错误:

data Course = Course { 
   id :: Int, 
   title :: String 
   } deriving (Eq, Show)
请注意,添加了数据构造函数名称(“课程”),并将“派生”更改为“派生”

这里也一样

satisfies :: [Course] -> Req -> Bool
将类型从[课程]更改为[课程]

course1 = Course 1 "One"
course2 = Course 2 "Two"
course3 = Course 3 "Three"
course4 = Course 4 "Four"
course5 = Course 5 "Five"

req1 = Single course2
req2 = Any [Single course2, Single course3, Single course5]
req3 = All [Single course1, Single course2]
req4 = Any [req2, req3]
req5 = All [req4, req1]
一些测试数据

satisfies cs (Single c) = c `elem` cs
符合单一课程的要求。其他两个都很简单,因为它们所做的大部分工作在前奏曲中已经有了定义,你可以像英语一样阅读它们:

satisfies cs (Single c) = c `elem` cs
satisfies cs (Any reqs) = any (satisfies cs) reqs
satisfies cs (All reqs) = all (satisfies cs) reqs
以下是您朋友的类型签名
any
all

any :: (a -> Bool) -> [a] -> Bool
all :: (a -> Bool) -> [a] -> Bool
它们都接受一个布尔函数,并对列表中的每个成员进行测试。由于我们有一个需求列表和一个测试函数(它
满足
递归使用并部分应用于已免除的课程),我们可以直接使用它们

让我们测试一下:

*TestSO15213421> satisfies [course1] req1
False
*TestSO15213421> satisfies [course2] req1
True
*TestSO15213421> satisfies [course1, course2] req1
True
*TestSO15213421> satisfies [course1, course2] req1
True
*TestSO15213421> satisfies [course1, course2] req3
True
*TestSO15213421> satisfies [course1, course3] req3
False
*TestSO15213421> satisfies [course1, course3] req2
True
*TestSO15213421> satisfies [course4] req2
False
*TestSO15213421> satisfies [course4] req5
False
*TestSO15213421> satisfies [course5] req2
True
*TestSO15213421> satisfies [course4] req4
False
*TestSO15213421> satisfies [course2] req4
True
*TestSO15213421> satisfies [course2, course3] req4
True
*TestSO15213421> satisfies [course5, course3] req4
True
*TestSO15213421> satisfies [course5, course3] req5
False

正如所料。

为什么您认为需要类型类?我猜你的意思是
满足::[Courses]->Req->Bool
,但我不确定我只是在学习。有更好的方法吗?等等,我会把它写成一个完美的答案,这正是我想要的。哦,我没有注意到,但我确实需要Req=Any[Req]| All[Req]的嵌套,因为我希望能够表示任意复杂的需求系统。我认为在这两者之间(以及单一的基本情况),我应该能够表达我能想到的任何依赖关系。好吧,那么这只是一个简单的问题,而不是仅仅使用简单的列表函数,使用稍微复杂一些的函数(你们必须自己编写它们,也许可以对任何情况进行递归。这并不是什么大问题,只是意味着你们不能从数据中拖拽东西。List@Kyle:这里有一些值得思考的东西:你打算如何表达“至少3门,但列表中不超过10门课程必须有“中级”一词”的要求在标题中,除非有7门或7门以上的课程id大于500,否则必须有4门“中级”课程?@yatima2975:哦,你说得对。我可能应该做一些不同的Int[Req]。谢谢!哈哈。事实上,我最终得出了这个确切的代码。非常酷。
*TestSO15213421> satisfies [course1] req1
False
*TestSO15213421> satisfies [course2] req1
True
*TestSO15213421> satisfies [course1, course2] req1
True
*TestSO15213421> satisfies [course1, course2] req1
True
*TestSO15213421> satisfies [course1, course2] req3
True
*TestSO15213421> satisfies [course1, course3] req3
False
*TestSO15213421> satisfies [course1, course3] req2
True
*TestSO15213421> satisfies [course4] req2
False
*TestSO15213421> satisfies [course4] req5
False
*TestSO15213421> satisfies [course5] req2
True
*TestSO15213421> satisfies [course4] req4
False
*TestSO15213421> satisfies [course2] req4
True
*TestSO15213421> satisfies [course2, course3] req4
True
*TestSO15213421> satisfies [course5, course3] req4
True
*TestSO15213421> satisfies [course5, course3] req5
False