USE*_*SFU 0 haskell if-statement tuples
我在Haskell中编写一个代码,它取一个0和1的列表,如[1,1,0,0,1,0,1]返回列表中0和1的数字出现的对(元组)(如( 3,4).
这是我的代码:
inc :: Int -> Int
inc x = (\x -> x + 1) x
count :: [Int] -> (Int,Int)
c = (0,0)
count x =
if null x
then c
else if head x == 0
then do
inc (fst c)
count (tail x)
else if head x == 1
then do
inc (snd c)
count (tail x)
Run Code Online (Sandbox Code Playgroud)
我也尝试过这种保护形式:
count :: [Int] -> (Int,Int)
c = (0,0)
count x
| null x = c
| head x == 0 = inc (fst c) >> count (tail x)
| head x == 1 = inc (snd c) >> count (tail x)
Run Code Online (Sandbox Code Playgroud)
主要问题是我不确定如何在一个then语句中实现两个函数.
你们正在考虑所有人.喜欢的东西do { inc (fst c); count (tail x) }
只会意义,如果c
是某种可变状态变量.哈斯克尔变量是不可变的,所以inc
不能修改的fst
的c
,它只能给你一个修改后的副本.如果您重写inc
为完全等效的简单形式,这可能会变得更加清晰:
inc x = x + 1
Run Code Online (Sandbox Code Playgroud)
(事实上,inc = (+1)
也会这样做.)
现在,count
你正试图通过递归循环继续并递增一个累加器变量.您可以这样做,但您需要明确将修改后的版本传递给递归调用:
count = go (0,0)
where go :: (Int,Int) -> [Int] -> (Int,Int)
go c x
| null x = c
| head x == 0 = go (first inc c) (tail x)
| head x == 1 = go (second inc c) (tail x)
Run Code Online (Sandbox Code Playgroud)
这种定义一个小的本地辅助函数的模式(go
只是一个任意的名称,我也可以称之为getTheCountingDone
),并将它用作递归的"循环体"在Haskell中非常常见.基本上go (0,0)
"初始化" c
到值(0,0)
,然后开始第一次循环迭代.对于第二次迭代,您可以递归到例如go (first inc c)
,即使用更新的c
变量再次启动循环.
我已经使用first
和second
增加了相应的元组字段.fst
只读取第一个字段,即给出它的值,而first
从元素更新函数创建一个元组更新函数.而不是import Control.Arrow
你也可以自己定义:
first :: (a->b) -> (a,y) -> (b,y)
first f (a, y) = (f a, y)
second :: (a->b) -> (x,a) -> (x,b)
second f (x, a) = (x, f a)
Run Code Online (Sandbox Code Playgroud)
(该Control.Arrow
版本实际上更通用,但您不必担心 - 您可以以相同的方式使用它.)
请注意,在Haskell 中解析列表head
并且tail
在Haskell中被大量避开:它很容易出错 - 在访问元素之前,您可能忘记检查列表是否为非空,这将引发令人讨厌的运行时错误.更好地使用模式匹配:
count = go (0,0)
where go c [] = c
go c (0:xs) = go (first inc c) xs
go c (1:xs) = go (second inc c) xs
Run Code Online (Sandbox Code Playgroud)
实际上这仍然不安全:你没有详尽的案件; 如果列表包含除零或1之外的任何内容,则函数将失败.也许你想要计算所有零和非零元素?
count = go (0,0)
where go c [] = c
go c (0:xs) = go (first inc c) xs
go c (_:xs) = go (second inc c) xs
Run Code Online (Sandbox Code Playgroud)