gpt4 book ai didi

Haskell - 无法将类型 `[Char]' 与 `Char' 匹配

转载 作者:行者123 更新时间:2023-12-04 22:18:27 25 4
gpt4 key购买 nike

我目前在 Haskell 中有以下代码

splitStringOnDelimeter :: String -> Char -> [String]

splitStringOnDelimeter "" delimeter = return [""]

splitStringOnDelimeter string delimeter = do
let split = splitStringOnDelimeter (tail string) delimeter
if head string == delimeter
then return ([""] ++ split)
else return ( [( [(head string)] ++ (head split) )] ++ (tail split))

如果我在 Haskell 终端(即 https://www.tryhaskell.org )中使用返回语句的值(例如 ( [( [(head "ZZZZ")] ++ (head ["first", "second", "third"]) )] ++ (tail ["first", "second", "third"]))[""] ++ ["first", "second", "third"][""] )运行它,那么我会从终端接收到与本地堆栈编译器不同的正确类型。此外,如果我还将 top return 语句更改为 return "" ,那么它不会提示那个我很确定是不正确的语句。

我的本地编译器与我的 Haskell 代码库的其余部分工作正常,这就是为什么我认为我的代码可能有问题......

最佳答案

Monad 类型类设计中的不幸之一是他们引入了一个名为 return 的函数。但是虽然在很多命令式编程语言中 return 是一个返回内容的关键字,但在 Haskell 中 return 有着完全不同的含义,它并没有真正返回任何东西。

您可以通过删除 return 来解决问题:

splitStringOnDelimeter :: String -> Char -> [String]
splitStringOnDelimeter "" delimeter = [""]
splitStringOnDelimeter string delimeter =
let split = splitStringOnDelimeter (tail string) delimeter in
if head string == delimeter
then ([""] ++ split)
else ( [( [(head string)] ++ (head split) )] ++ (tail split))
return :: Monad m => a -> m a 用于将值(类型为 a )包装在 monad 中。因为这里你的签名暗示了一个列表,Haskell 会假设你在寻找列表 monad。所以这意味着你 return 会将 [""] 包装到另一个列表中,所以你会用 return [""] 隐式地编写(在这种情况下), [[""]] ,这当然与 [String] 不匹配。
do 也是如此,您再次创建了一个 monadic 函数,但在这里您的函数与 monads 没有太大关系。

请注意,名称 return 本身并不坏,但由于几乎所有命令式语言都为其附加了(几乎)等效的含义,因此大多数人认为它在函数式语言中的工作方式相同,但事实并非如此。

请注意,您使用了 headtail 等函数。这些通常被视为反模式:您可以改用模式匹配。我们可以将其重写为:
splitStringOnDelimeter :: String -> Char -> [String]
splitStringOnDelimeter "" delimeter = [""]
splitStringOnDelimeter (h:t) delimeter | h == delimeter = "" : split
| otherwise = (h : sh) : st
where split@(sh:st) = splitStringOnDelimeter t delimeter

通过使用模式匹配,我们可以肯定地知道 string 有一个头部 h 和一个尾部 t ,我们可以直接在表达式中使用它们。这使得表达式更短且更具可读性。虽然 if - then - else 子句本身并不是反模式,但我个人认为守卫在语法上更干净。因此,我们在这里使用了一个 where 子句,我们在这里调用 splitStringOnDelimter t delimeter ,并且我们将它与 split (以及与 (sh:st) )进行模式匹配。我们知道这将始终匹配,因为 basecase 和 inductive case 总是产生一个列表,其中至少有一个元素。这再次允许 use 编写一个简洁的表达式,我们可以直接使用 shst ,而不是调用 headtail

如果我在本地测试这个函数,我得到:
Prelude> splitStringOnDelimeter "foo!bar!!qux" '!'
["foo","bar","","qux"]

作为外卖信息,我认为你最好避免使用 returndo ,除非你知道这个函数和关键字( do 是一个关键字)的真正含义。在函数式编程的上下文中,这些具有不同的含义。

关于Haskell - 无法将类型 `[Char]' 与 `Char' 匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49611620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com