我最近开始学习Haskell,我正在尝试重写我在Haskell中使用python进行访谈时所做的一些事情.我正在尝试将字符串从camel case转换为下划线("myVariableName" - >"my_variable_name"),如果第一个字符为大写,则会抛出错误.
这就是我所拥有的:
import qualified Data.Char as Char
translate_java :: String -> String
translate_java xs = translate_helper $ enumerate xs
where
translate_helper [] = []
translate_helper ((a, num):xs)
| num == 1 and Char.isUpper a = error "cannot start with upper"
| Char.isUpper a = '_' : Char.toLower a : translate_helper xs
| otherwise = a : translate_helper xs
enumerate :: (Num b, Enum b) => [a] -> [(a,b)]
enumerate xs = zip xs [1..]
Run Code Online (Sandbox Code Playgroud)
我意识到我很可能会以一种奇怪的方式解决这个问题,而且我喜欢有关更好的方法来实现这一点的建议,但我也希望能够编译它.这是我现在得到的错误:
Prelude> :r
[1 of 1] Compiling Main ( translate.hs, interpreted )
translate.hs:4:20:
No instance for (Num
(([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))
arising from a use of `translate_helper' at translate.hs:4:20-35
Possible fix:
add an instance declaration for
(Num (([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))
In the first argument of `($)', namely `translate_helper'
In the expression: translate_helper $ enumerate xs
In the definition of `translate_java':
translate_java xs
= translate_helper $ enumerate xs
where
translate_helper [] = []
translate_helper ((a, num) : xs)
| num == 1 and Char.isUpper a
= error "cannot start with upper
"
| Char.isUpper a
= '_' : Char.toLower a : transla
te_helper xs
| otherwise = a : translate_help
er xs
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
对这里发生的事情的任何解释都会很棒.我真的不明白"(Num(([Bool] - > Bool) - >(Char - > Bool) - > Char - > t))"来自.我认为translate_helper的类型声明类似于[(a,b)] - > [a]?
必须更换and的&&.第一个是一个函数(前缀),它接收一个布尔值列表并计算它们的全部.第二个是真正的逻辑和.但错误消息有点令人困惑.每当我收到如此奇怪的错误消息时,我通常会开始使用类型签名来注释我的代码.然后编译器能够为您提供更详细的错误描述.
其他人提到你应该使用(&&)而不是and,所以我会回答你的另一个问题:不,我不认为你会以一种奇怪的方式解决这个问题.
但是......我觉得它可以更优雅!
translate_java (x:xs) | isUpper x = error "cannot start with an upper"
translate_java xs = concatMap translate xs where
translate x = ['_' | isUpper x] ++ [toLower x]
Run Code Online (Sandbox Code Playgroud)
这里有一些有趣的事情:
concatMap在很多情况下,该功能非常方便.它只是一个map跟随的concat.如果我自己写这篇文章,我可能会用xs >>= translate.['_' | isUpper x]是列表理解; 这是一个可爱的习惯用法,用于制作一个包含0或1个元素的列表,具体取决于谓词是否成立.除此之外,代码应该是相当不言自明的.