如何匹配签名上的空列表类型包装器类型。针对类型签名函数 returns Nil
How to match empty List type wrapper type on signature. Against type signature the function returns Nil
仍然是关于“PureScript 示例”的第 3 章(不相关 )。函数 removeDuplicates
returns me Nil on test 和 repl returns Nil 而不是 AddressBook 这有点令人失望,因为我希望编译器可以防止这种情况。另一方面,我似乎也无法匹配一个空的地址簿(type AddressBook = List Entry
)。
代码(省略无关部分):
emptyBook :: AddressBook
emptyBook = empty
findEntry :: String -> String -> AddressBook -> Maybe Entry
findEntry firstName lastName = head <<< filter filterEntry
where
filterEntry :: Entry -> Boolean
filterEntry entry = entry.firstName == firstName && entry.lastName == lastName
-- implementation which fails test/breaks compiler warranty
import Data.AddressBook
import Prelude
import Control.Plus (empty)
import Data.List (List(..), filter, foldl, head, null, tail, (:))
removeDuplicates :: AddressBook -> AddressBook
removeDuplicates book = skipIfDup emptyBook book
skipIfDup :: AddressBook -> AddressBook -> AddressBook
skipIfDup newBook Nil = newBook
skipIfDup newBook (entry : book) =
skipIfDup newerBook book
where
newerBook :: AddressBook
newerBook =
case (findEntry entry.firstName entry.lastName newBook) of
Nothing -> newBook
Just e -> insertEntry e newBook
除了 Nil
,我还尝试了 Data.List.null
和 emptyBook
(但我相信符号会反弹),结果相同。使用 []
不编译,将 case 带到主用例的 if-else 语句中,但随后编译器抱怨没有转换 Nil 用例。
这是怎么回事?为什么编译器允许 Nil 返回函数?我应该如何使用 null
或任何必要的符号正确测试空 List/AddressBook 的用例?
REPL 输出:
> removeDuplicates book with duplicate
Nil
测试用例输出:
☠ Failed: Exercise - removeDuplicates because expected ({ address: { city: "Faketown", state: "CA", street: "123 Fake St." }, firstName: "John", lastName: "Smith" } : { address: { city: "Arlen", state: "TX", street: "84 Rainey St." }, firstName: "Peggy", lastName: "Hill" } : { address: { city: "Springfield", state: "USA", street: "740 Evergreen Terrace" }, firstName: "Ned", lastName: "Flanders" } : Nil), got Nil
与 C# 或 JavaScript 或您来自的任何地方不同,PureScript 中的 Nil
和 null
不是 special/magic“未初始化引用”类型的事情。 PureScript 根本没有这些。就 PureScript 编译器所知,一切总是“定义的”。
Nil
只是 List
构造函数的名称。看看 the List
definition:
data List a = Nil | Cons a (List a)
它只是一个 sum 类型,有两个构造函数,其中一个名为 Nil
。可以命名为 Abracadabra
并且仍然可以正常工作,但显然库作者希望名称具有某种意义,我猜?愚蠢的人。所以 Nil
在这种情况下应该表示“空列表”。
同样,null
只是一个函数名。 Here's its definition:
null :: forall a. List a -> Boolean
null Nil = true
null _ = false
只是 returns true
是给定的列表是一个空列表,否则 false
。
现在,您的实际问题出在这里:
newerBook =
case (findEntry entry.firstName entry.lastName newBook) of
Nothing -> newBook
Just e -> insertEntry e newBook
看看你在做什么:你试图在 newBook
中找到条目,如果找到,你将相同的条目插入到 newBook
中。这样 newBook
现在就有两个这样的条目。这真的是你想要做的吗?
根据我对原始问题的模糊理解,你真正想要做的是将 entry
添加到 newBook
如果它是 而不是 已经。如果 是 在那里,请单独留下 newBook
:
newerBook =
case (findEntry entry.firstName entry.lastName newBook) of
Nothing -> entry : newBook
Just _ -> newBook
仍然是关于“PureScript 示例”的第 3 章(不相关 removeDuplicates
returns me Nil on test 和 repl returns Nil 而不是 AddressBook 这有点令人失望,因为我希望编译器可以防止这种情况。另一方面,我似乎也无法匹配一个空的地址簿(type AddressBook = List Entry
)。
代码(省略无关部分):
emptyBook :: AddressBook
emptyBook = empty
findEntry :: String -> String -> AddressBook -> Maybe Entry
findEntry firstName lastName = head <<< filter filterEntry
where
filterEntry :: Entry -> Boolean
filterEntry entry = entry.firstName == firstName && entry.lastName == lastName
-- implementation which fails test/breaks compiler warranty
import Data.AddressBook
import Prelude
import Control.Plus (empty)
import Data.List (List(..), filter, foldl, head, null, tail, (:))
removeDuplicates :: AddressBook -> AddressBook
removeDuplicates book = skipIfDup emptyBook book
skipIfDup :: AddressBook -> AddressBook -> AddressBook
skipIfDup newBook Nil = newBook
skipIfDup newBook (entry : book) =
skipIfDup newerBook book
where
newerBook :: AddressBook
newerBook =
case (findEntry entry.firstName entry.lastName newBook) of
Nothing -> newBook
Just e -> insertEntry e newBook
除了 Nil
,我还尝试了 Data.List.null
和 emptyBook
(但我相信符号会反弹),结果相同。使用 []
不编译,将 case 带到主用例的 if-else 语句中,但随后编译器抱怨没有转换 Nil 用例。
这是怎么回事?为什么编译器允许 Nil 返回函数?我应该如何使用 null
或任何必要的符号正确测试空 List/AddressBook 的用例?
REPL 输出:
> removeDuplicates book with duplicate
Nil
测试用例输出:
☠ Failed: Exercise - removeDuplicates because expected ({ address: { city: "Faketown", state: "CA", street: "123 Fake St." }, firstName: "John", lastName: "Smith" } : { address: { city: "Arlen", state: "TX", street: "84 Rainey St." }, firstName: "Peggy", lastName: "Hill" } : { address: { city: "Springfield", state: "USA", street: "740 Evergreen Terrace" }, firstName: "Ned", lastName: "Flanders" } : Nil), got Nil
与 C# 或 JavaScript 或您来自的任何地方不同,PureScript 中的 Nil
和 null
不是 special/magic“未初始化引用”类型的事情。 PureScript 根本没有这些。就 PureScript 编译器所知,一切总是“定义的”。
Nil
只是 List
构造函数的名称。看看 the List
definition:
data List a = Nil | Cons a (List a)
它只是一个 sum 类型,有两个构造函数,其中一个名为 Nil
。可以命名为 Abracadabra
并且仍然可以正常工作,但显然库作者希望名称具有某种意义,我猜?愚蠢的人。所以 Nil
在这种情况下应该表示“空列表”。
同样,null
只是一个函数名。 Here's its definition:
null :: forall a. List a -> Boolean
null Nil = true
null _ = false
只是 returns true
是给定的列表是一个空列表,否则 false
。
现在,您的实际问题出在这里:
newerBook =
case (findEntry entry.firstName entry.lastName newBook) of
Nothing -> newBook
Just e -> insertEntry e newBook
看看你在做什么:你试图在 newBook
中找到条目,如果找到,你将相同的条目插入到 newBook
中。这样 newBook
现在就有两个这样的条目。这真的是你想要做的吗?
根据我对原始问题的模糊理解,你真正想要做的是将 entry
添加到 newBook
如果它是 而不是 已经。如果 是 在那里,请单独留下 newBook
:
newerBook =
case (findEntry entry.firstName entry.lastName newBook) of
Nothing -> entry : newBook
Just _ -> newBook