我目前正在Haskell中使用摩尔斯电码编码器。这是我第一次在Haskell工作,我发现很难以“功能”的方式思考。到目前为止,我已经想出了这个:
module Formative1
(encode, decode, toTree, toTable)
where
import safe Lib
encode :: String -> [MorseUnit]
encode str = codeText(words str)
codeWord :: String -> [MorseUnit]
codeWord word = map codeSymbol word
codeText :: [String] -> [MorseUnit]
codeText list = map codeWord list
解释我的代码:
encode
是主要功能。它使用words
将句子分解为单词列表。 codeText
用于将函数codeWord
应用于列表中的每个单词。 codeWord
然后maps
覆盖每个字词中的每个字符,并使用MorseUnit
找到codeSymbol
。
我对此解决方案有两个问题:
问题1:由于[MorseUnit]
不匹配[[MorseUnit]]
,每次运行时都会收到错误,我相信这是因为我使用了map
两次,所以它在一个列表。但是,如果不使用map
,我就无法想到另一种解决方案。
问题2:摩尔斯电码规则规定,在每个字母之后,应该有一个“shortGap”,并且在每个字之后,应该有一个“mediumGap”。我不知道如何在列表的每个元素之间插入任何字符串(我会在map codeSymbol word
中的每个元素之间插入shortGap,因此shortGaps位于每个字母之间,我会在{{1}中的每个元素之间插入mediumGap所以mediumGaps在每个单词之间)。我也不明白我会在什么时候添加差距,因为我不想意外地将map codeWord list
应用于任何差距并替换它们。
任何解决方案都会有所帮助!谢谢。
答案 0 :(得分:1)
错误是由两张地图引起的。但您也可以从类型签名中看到它:
codeText list = map codeWord list (where list :: [String])
codeWord :: String -> [MorseUnit]
map :: (a -> b) -> [a] -> [b]
如果您将(a -> b)
替换为(String -> [MorseUnit])
,则[a]
变为[String]
,[b]
变为[[MorseUnit]]
。
与数学一样,有很多方法可以做到这一点。显然你只能concat
得到的结果列表。请注意直截了当的[[a]] -> [a]
签名。
请注意,之后会有concatMap
。您可以使用它来代替map
,这样会使结果变平。
为了进一步让您感到困惑,如果您发现参数在声明和定义中都显示在最后,您可以省略它:
codeText = concatMap codeWord
我建议您使用Hoogle搜索所需的功能签名。
首先,由于你需要区分单词和符号,在我看来你可能不需要这么早地压扁列表。我不熟悉莫尔斯电码,所以我不完全明白你想做什么。如果你能在类型和签名中表达你的概念,那就更清楚了。我的建议是查看intersperse :: a -> [a] -> [a]
或intercalate :: [a] -> [[a]] -> [a]
以填补您的空白。需要使用import Data.List
导入它们。
答案 1 :(得分:-1)
碰巧,你需要Monad。 Haskell有许多(我的意思是很多)Monad教程可以在线获得,我鼓励你利用其中的一个。
列表类型[]
是Monad
类型类的实例。没有详细说明,这意味着有一个函数concatMap :: (a -> [b]) -> [a] -> [b]
。从类型中,您可以推断它与map :: (a -> b) -> [a] -> [b]
类似,但以某种方式展平(或concat
s)list-of-list结构。
concatMap
为(>>=) :: Monad m => (a -> m b) -> m a -> m b
,专门针对m ~ []
。
我们也可以忽略你的函数的参数,因为Haskell中的函数是curry。
encode :: String -> [MorseUnit]
encode = codeText . words
codeWord :: String -> [MorseUnit]
codeWord = map codeSymbol
codeText :: [String] -> [MorseUnit]
codeText = concatMap codeWord
关于第二个问题,请尝试使用intercalate
。举个例子:
> intercalate ", " ["hello", "world"]
"hello, world"