所以我试图在haskell中编写一个函数,它执行以下操作: 1.输入是一个字符串 2.函数首先删除字符串的所有字母,只保留数字 3.函数将字符串数转换为int数 4.函数将字符串中的数字相加并打印出来
我的代码直到'第3步
func str =
do
str <- filter (< 'a') str
str2 <- map digitToInt str
return str2
如果我用mapToInt删除第4行它不会起作用,直到步骤#2很好但我不知道这里的问题是什么
错误是一个无法匹配的预期类型[Char]与实际类型Char
提前谢谢
答案 0 :(得分:7)
你根本不想要do
符号,只是普通的变量绑定。所以:
func str = str2 where
str1 = filter (<'a') str
str2 = map digitToInt str1
跟踪最近使用的名称很烦人,不是吗?此外,它很容易出错,并在某处或类似地点击str
而不是str1
。输入功能组成:
func str = str2 where
str2 = (map digitToInt . filter (<'a')) str
事实上,我会内联str2
的定义,然后完全忽略str
:
func = map digitToInt . filter (<'a')
我希望isDigit
优于(<'a')
;我们可以在同一时间投入一笔款项。
func = sum . map digitToInt . filter isDigit
在我看来,读起来很干净。
答案 1 :(得分:1)
你可以使用do
表示法,因为字符串是列表,列表是monad。但是看起来像这样:
func :: String -> [Int]
func str = do
c <- filter (< 'a') str -- Get one character
return (digitToInt c) -- Change that character to a integer
c
的价值是多少?它不仅仅是一个角色,而是所有。列表monad模型非确定性。想象一下,func
生成自己的多个副本,每个副本从输入字符串中选择不同的字符c
。 return
从结果中创建一个新列表,monad负责将各个列表粘合到一个最终列表中。如果你将它与解构的形式进行比较,那就更清楚了。
func str = filter (< 'a') str >>= \c -> return (digitToInt c)
自xs >>= f = concatMap f xs
个实例中的return x = [x]
和Monad []
后,它变为:
func str = concatMap (\c -> [digitToInt c]) (filter (< 'a') str)
但是,monadic形式不是必需的,因为你的函数只需要使用Functor
的{{1}}实例,因为第一个列表中的每个元素都对应于最终名单:
[]