- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
作为函数数据类型分配的一部分,我们被要求在 Haskell 中给出不同的队列实现,下面给出了其中的两个。
来自 OO 世界,第一个 react 是让他们实现一个通用接口(interface),以便他们可以例如分享测试代码。从我们在 Haskell 上读到的内容来看,这转化为两种数据类型,它们是通用类型类的实例。这部分相当简单:
data SimpleQueue a = SimpleQueue [a]
data FancyQueue a = FancyQueue ([a], [a])
class Queue q where
empty :: q a
enqueue :: a -> q a -> q a
dequeue :: q a -> (a, q a)
instance Queue SimpleQueue where
empty = SimpleQueue []
enqueue e (SimpleQueue xs) = SimpleQueue $ xs ++ [e]
dequeue (SimpleQueue (x:xs)) = (x, SimpleQueue xs)
instance Queue FancyQueue where
empty = FancyQueue ([], [])
enqueue e (FancyQueue (h, t)) =
if length h > length t
then FancyQueue (h, e:t)
else FancyQueue (h ++ reverse (e:t), [])
dequeue (FancyQueue ((e:h), t)) =
if length h > length t
then (e, FancyQueue (h, t))
else (e, FancyQueue (h ++ reverse t, []))
经过大量的折腾,我们得出了以下编写测试用例(使用 HUnit)的工作方式,该测试用例使用相同的函数 f
测试两种实现:
f :: (Queue q, Num a) => q a -> (a, q a)
f = dequeue . enqueue 4
makeTest = let (a, _) = f (empty :: SimpleQueue Int)
(b, _) = f (empty :: FancyQueue Int)
in assertEqual "enqueue, then dequeue" a b
test1 = makeTest
main = runTestTT (TestCase test1)
正如代码所示,我们非常感兴趣的是让函数 makeTest
将测试函数作为参数,这样我们就可以使用它来生成多个测试用例而无需复制代码将函数应用到他们身上:
makeTest t = let (a, _) = t (empty :: SimpleQueue Int)
(b, _) = t (empty :: FancyQueue Int)
in assertEqual "enqueue, then dequeue" a b
test1 = makeTest f
main = runTestTT (TestCase test1)
但是,编译失败并出现错误
queue.hs:52:30:
Couldn't match expected type `FancyQueue Int'
with actual type `SimpleQueue Int'
In the first argument of `t', namely `(empty :: SimpleQueue Int)'
In the expression: t (empty :: SimpleQueue Int)
In a pattern binding: (a, _) = t (empty :: SimpleQueue Int)
我们的问题是是否有某种方法可以使这项工作:是否可以编写一个函数来生成我们的单元测试?一个接受一个函数并将其应用于两个实现的方式,以避免重复应用该函数的代码?此外,非常欢迎对上述错误进行解释。
编辑
根据以下答案,我们最终得出以下结论:
{-# LANGUAGE RankNTypes #-}
import Test.HUnit
import Queue
import SimpleQueue
import FancyQueue
makeTest :: String -> (forall q a. (Num a, Queue q) => q a -> (a, q a)) -> Assertion
makeTest msg t = let (a, _) = t (empty :: SimpleQueue Int)
(b, _) = t (empty :: FancyQueue Int)
in assertEqual msg a b
test1 = makeTest "enqueue, then dequeue" $ dequeue . enqueue 4
test2 = makeTest "enqueue twice, then dequeue" $ dequeue . enqueue 9 . enqueue 4
test3 = makeTest "enqueue twice, then dequeue twice" $ dequeue . snd . dequeue . enqueue 9 . enqueue 4
tests = TestList $ map (\ test -> TestCase test) [test1, test2, test3]
main = runTestTT tests
我想知道 makeTest
上的类型注释是否是正确的编写方式?我试着摆弄它,但这是我唯一可以开始工作的事情。只是我认为部分 (Num a, Queue q) =>
应该总是在类型本身之前。但也许这只是一个约定?或者对于更高级别的类型来说一切都不同?无论如何,可以这样写类型吗?
另外,这里并不重要,但出于好奇;使用此扩展是否会影响性能(显着)?
最佳答案
是的,您需要一个名为 Rank2Types
的语言扩展。它允许这样的功能
makeTest :: (forall q a. (Num a, Queue q) => q a -> (a, q a)) -> Assertion
makeTest t = let (a, _) = t (empty :: SimpleQueue Int)
(b, _) = t (empty :: FancyQueue Int)
in assertEqual "enqueue, then dequeue" a b
现在您要确保收到的函数是多态的,因此您可以将它应用于 SimpleQueue
和 FancyQueue
。
否则,Haskell 会将 t
的第一个参数与 SimpleQueue
统一起来,然后当你尝试将它用于 FancyQueue
时会生气>。换句话说,默认情况下,Haskell 使函数参数是单态的。为了使它们具有多态性,尽管您必须使用显式签名,但 Haskell 不会推断它。
要使用此扩展程序,您需要启用它
{-# LANGUAGE RankNTypes #-}
在文件的顶部。见 here有关此扩展程序的作用及其工作原理的详细说明。
这就是正确输入的方式。 Haskell 隐式转
foo :: Show a => a -> b -> c
进入
foo :: forall a b c. Show a => a -> b -> c
对于更高等级的类型,您将 forall
移动到 lambda 中,并且约束随之移动。您不能将约束一直放在左侧,因为相关的类型变量甚至不在范围内。
关于unit-testing - 单元测试功能数据结构的几种实现,无需重复代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20621301/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!