Map.insert无故提示Haskell错误
Map.insert prompting an error in Haskell without reason
这是我正在使用的功能:
threeWordFunction :: [String] -> Map.Map String [String] -> String
threeWordFunction [x, y, z] orbitingData = do
Map.insert z [x, y] orbitingData
""
导致以下错误:
src\MyLib.hs:40:6: error:
* Couldn't match type `Map.Map String' with `[]'
Expected type: [[String]]
Actual type: Map.Map String [String]
* In a stmt of a 'do' block: Map.insert z [x, y] orbitingData
In the expression:
do Map.insert z [x, y] orbitingData
""
In an equation for `threeWordFunction':
threeWordFunction [x, y, z] orbitingData
= do Map.insert z [x, ....] orbitingData
""
|
40 | Map.insert z [x, y] orbitingData
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我尝试了一大堆修复方法,但没有发现任何可能导致此错误的方法。该函数只是试图将字符串添加到地图中,没什么特别的。任何帮助将不胜感激。
问题
正如一些贡献者所说,do
是问题所在。
但是,让我尝试分解你想要的(如我所见)和你所做的。
threeWordFunction :: [String] -> Map.Map String [String] -> String
声明函数的类型。这是你打算做的。对于 String
和 Map
的列表,您想提供 String
。如果我在 Haskell 中读到这篇文章,我会推断您可能想使用 Map
来提取一些有用的东西来构建 String
。实际上,您的函数的唯一输出是 String
。由于 Map
不是输出,任何修改都将“丢失”。
当我读到你想做什么时,你声称你想在 Map
中插入一个值。所以我想你想输出结果 Map
。在这里我可以推断出你的第一个错误:你认为有副作用。我假设您想在函数内部修改 Map
,并且您期望 Map 将在函数外部进行修改。但这不是 Haskell 的工作方式。这就是大多数具有命令式特性的语言的工作方式。
所以要做这个你要用do
这个词。这背后的想法是提供一系列指令,例如 C-block 中带有花括号的指令。这是错误的。在 Haskell 中,do
词是语法糖,它指出了你在一个 monad 中的事实......所以你的计算结果可能是一个 monad。但这不是函数类型所说的。所以编译器会产生错误。
怎么做才能和你的类型保持一致
考虑到类型,Chi提供的解决方案。
threeWordFunction [x, y, z] orbitingData = let newMap = Map.insert z [x, y] orbitingData in ""
编译器不会再报错了。您构建了一个新地图 newMap
,它可以按照您想要的方式进行修改。您提供 String
""
作为输出。但是, newMap
将永远无法在您的函数之外访问。所以插入没用。
你可以做什么来满足你的需求
更改类型...Haskell 中的类型提供了明确定义预期有效解决方案(或多或少)的规范。
因此您可能需要明确提供地图的东西。
threeWordFunction :: [String] -> Map.Map String [String] -> Map.Map String [String]
或一个映射和一个字符串
threeWordFunction :: [String] -> Map.Map String [String] -> (Map.Map String [String], String)
您也可以像 State 一样使用 monad,但对于您的水平来说它可能太多了。
考虑到新类型,您现在可以 return 一个您需要的实体。
threeWordFunction :: [String] -> Map.Map String [String] -> (Map.Map String [String], String)
threeWordFunction [x, y, z] orbitingData =
let newMap = Map.insert z [x, y] orbitingData
in (newMap, "")
注意,如果您总是想提供一个 ""
作为字符串,这可能表明您不需要它。
希望这能帮助您理解问题。
这是我正在使用的功能:
threeWordFunction :: [String] -> Map.Map String [String] -> String
threeWordFunction [x, y, z] orbitingData = do
Map.insert z [x, y] orbitingData
""
导致以下错误:
src\MyLib.hs:40:6: error:
* Couldn't match type `Map.Map String' with `[]'
Expected type: [[String]]
Actual type: Map.Map String [String]
* In a stmt of a 'do' block: Map.insert z [x, y] orbitingData
In the expression:
do Map.insert z [x, y] orbitingData
""
In an equation for `threeWordFunction':
threeWordFunction [x, y, z] orbitingData
= do Map.insert z [x, ....] orbitingData
""
|
40 | Map.insert z [x, y] orbitingData
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我尝试了一大堆修复方法,但没有发现任何可能导致此错误的方法。该函数只是试图将字符串添加到地图中,没什么特别的。任何帮助将不胜感激。
问题
正如一些贡献者所说,do
是问题所在。
但是,让我尝试分解你想要的(如我所见)和你所做的。
threeWordFunction :: [String] -> Map.Map String [String] -> String
声明函数的类型。这是你打算做的。对于 String
和 Map
的列表,您想提供 String
。如果我在 Haskell 中读到这篇文章,我会推断您可能想使用 Map
来提取一些有用的东西来构建 String
。实际上,您的函数的唯一输出是 String
。由于 Map
不是输出,任何修改都将“丢失”。
当我读到你想做什么时,你声称你想在 Map
中插入一个值。所以我想你想输出结果 Map
。在这里我可以推断出你的第一个错误:你认为有副作用。我假设您想在函数内部修改 Map
,并且您期望 Map 将在函数外部进行修改。但这不是 Haskell 的工作方式。这就是大多数具有命令式特性的语言的工作方式。
所以要做这个你要用do
这个词。这背后的想法是提供一系列指令,例如 C-block 中带有花括号的指令。这是错误的。在 Haskell 中,do
词是语法糖,它指出了你在一个 monad 中的事实......所以你的计算结果可能是一个 monad。但这不是函数类型所说的。所以编译器会产生错误。
怎么做才能和你的类型保持一致
考虑到类型,Chi提供的解决方案。
threeWordFunction [x, y, z] orbitingData = let newMap = Map.insert z [x, y] orbitingData in ""
编译器不会再报错了。您构建了一个新地图 newMap
,它可以按照您想要的方式进行修改。您提供 String
""
作为输出。但是, newMap
将永远无法在您的函数之外访问。所以插入没用。
你可以做什么来满足你的需求
更改类型...Haskell 中的类型提供了明确定义预期有效解决方案(或多或少)的规范。
因此您可能需要明确提供地图的东西。
threeWordFunction :: [String] -> Map.Map String [String] -> Map.Map String [String]
或一个映射和一个字符串
threeWordFunction :: [String] -> Map.Map String [String] -> (Map.Map String [String], String)
您也可以像 State 一样使用 monad,但对于您的水平来说它可能太多了。
考虑到新类型,您现在可以 return 一个您需要的实体。
threeWordFunction :: [String] -> Map.Map String [String] -> (Map.Map String [String], String)
threeWordFunction [x, y, z] orbitingData =
let newMap = Map.insert z [x, y] orbitingData
in (newMap, "")
注意,如果您总是想提供一个 ""
作为字符串,这可能表明您不需要它。
希望这能帮助您理解问题。