haskell - 这个 Haskell 代码在多大程度上满足了这个规范?
问题描述
清单 1是来自论文的 Haskell 类签名和实例。如果一个人在给定的房子或给定的房间中,该isIn person house
函数应该返回 true。
清单 1
class CONTAINMENT container for where
isIn :: for -> container -> Bool
instance CONTAINMENT House Person where
isIn person house =
(container person = house) || isIn (container person) house
的定义中有错误isIn person house
,我希望在这篇文章中忽略这些错误。
相反,我希望将清单 1与下面的文本描述(来自论文)一起考虑作为规范(即说明符意图的合理表示)。
文字说明
isIn 的公理使用 Person (person) 和 House (house) 类型的个体变量,并声明如果房子包含她,或者递归地,如果房子包含包含她。为了说明这一点,我使用状态表示作为标记的字段容器,这里假设是为人员类型定义的。
从规范看来:
- 一个人可能在一个房间里。
- 房间可能在房子里。
- 一个人可能直接在一个房子里,没有任何房间信息。
- 一个人可能在一个房子里的房间里,因此可以被认为是在房子里。
- 为了有用,房间需要有关包含它的房子的信息。
- 该人包含有关其位置的信息。一个人可以同时在一个房间和包含该房间的房子里吗?换句话说,我们是否有一个包容性或排他性或 in
isIn
? 从现实世界的领域来看:每个房间都必须在房子里,不可能在不在房子里的房间里。
清单 2是我尝试编写 Haskell 代码来实现Specification。我添加了辅助函数 (
getHouse
,getRoom
,getRooms
) 和一个CONTAINER
实例,用于为两者和Room
提供重载。我还为、和添加了数据类型 。isIn
House
Room
House
Room
Person
清单 2
{-# LANGUAGE MultiParamTypeClasses #-}
data Room = Room Int deriving (Show,Eq)
data Rooms = Rooms [Room] deriving (Show,Eq)
data House = House Int Rooms deriving (Show,Eq)
data Person = Person {container :: House } deriving (Show,Eq)
getRooms::House->Rooms
getRooms (House n rooms) = rooms
getHouse::Person->House
getHouse p = container p
getRoom::House->Room
getRoom (House n (Rooms (x:xs))) = x
class CONTAINMENT container for where
isIn :: for -> container -> Bool
instance CONTAINMENT House Person where
isIn person (House n (Rooms rooms)) = (container person) == (House n (Rooms rooms)) || isIn person (getRooms (House n (Rooms rooms)))
instance CONTAINMENT Rooms Person where
isIn person (Rooms []) = False
isIn person (Rooms (room:rooms)) = (room == getRoom(getHouse(person))) || isIn person (Rooms rooms)
r1 = Room 1
r2 = Room 2
h1 = House 1 (Rooms [])
h2 = House 2 (Rooms [r1])
h3 = House 3 (Rooms [r1,r2])
p1 = Person {container = h1}
p2 = Person {container = h2}
p3 = Person {container = h3}
personInHoseNoRooms = isIn p1 h1
personInHoseNoRoomsNotIn = isIn p1 h2
personInRoomInHouse = isIn p2 h2
personIn2ndRoomInHouse = isIn p3 h3
该代码似乎与规范大体一致。但是,我看到一些问题:
- 如果 disjunct in 的第一个参数
isIn
为假,而第二个参数为真,那么我们得到的信息是一个人在一个房间里,但不在包含该房间的房子里。这在我看来是一个逻辑矛盾,一个人不在房子 A,而是在房子 A 的房间里。这可能是我对规范或编码的理解有误。 - 递归一词通常适用于单一日期类型,但在重载
isIn
后适用于House
andRooms
,其中House
结构包含Rooms
. 同样,这可能是我的一个错误。 - 就目前而言,没有提到全球唯一的房间标识符。相同的房间号可能出现在不同的房屋中,这可能会产生模棱两可的结果。我认为这些
Room-House-Person
关系存在一些更深层次的问题,我无法清楚地表达出来。
问题
- 关于如何克服上述问题的任何编码建议。
- 或者,实际上是否可以实施规范?
解决方案
通过一些最小的更改,至少它可以在 GHC 中编译:
{-# LANGUAGE MultiParamTypeClasses #-}
data Room = Room Int deriving (Show,Eq)
data Rooms = Rooms [Room] deriving (Show,Eq)
data House = House Int Rooms deriving (Show,Eq)
data Person = Person {container :: House } deriving (Show,Eq)
getRooms :: House -> Rooms
getRooms (House n rooms) = rooms
getHouse :: Person -> House
getHouse p = container p
getRoom :: House -> Room
getRoom (House n (Rooms (x:xs))) = x
class Containment c f where
isIn :: f -> c -> Bool
instance Containment House Person where
isIn person (House n (Rooms rooms)) = (container person) == (House n (Rooms rooms)) || isIn person (getRooms (House n (Rooms rooms)))
instance Containment Rooms Person where
isIn person (Rooms []) = False
isIn person (Rooms (room:rooms)) = (room == getRoom(getHouse(person))) || isIn person (Rooms rooms)
r1 = Room 1
r2 = Room 2
h1 = House 1 (Rooms [])
h2 = House 2 (Rooms [r1])
h3 = House 3 (Rooms [r1,r2])
p1 = Person {container = h1}
p2 = Person {container = h2}
p3 = Person {container = h3}
personInHoseNoRooms = isIn p1 h1
personInHoseNoRoomsNotIn = isIn p1 h2
personInRoomInHouse = isIn p2 h2
personIn2ndRoomInHouse = isIn p3 h3
所以关于你的问题,是的,它可以在 Haskell 中实现。
关于声明:
如果房子包含她,或者递归地,如果房子包含一个包含她的容器(例如,一个房间)。
我同意你的说法,这recursively
不是正确的词,应该是transitively
。
推荐阅读
- typescript - 在 Webpack Visual Studio 2017 .NET Core 2.2 捆绑的 Chrome 中调试 Typescript
- ios - 测试给定的 iPhone 是否支持展开模式下的拆分视图
- c# - C# 控制台应用程序 - 运行节点 JS 脚本文件
- wordpress - 如何创建可以设置全局元/变量的管理页面?
- java - 如何显示2种数据库信息?
- prolog - 如何让程序在控制台中编译和显示
- python-3.x - 替换第一次出现在字符串列表中的字符
- azure-devops - 将测试计划复制到不同的项目
- flutter - 在颤动中增加抽屉的宽度
- php - 如何遍历数组以获取多个要上传的文件