在Haskell上定义一个布尔函数,用于确定元素在列表中是否出现一次
因此,我试图在Haskell中定义一个函数,如果给定一个整数和一系列整数,无论该整数是否只出现一次,都会给出“true”或“false” 到目前为止,我已经: let one::Eq a=>a->[a]->Bool;一次x l=在Haskell上定义一个布尔函数,用于确定元素在列表中是否出现一次,haskell,Haskell,因此,我试图在Haskell中定义一个函数,如果给定一个整数和一系列整数,无论该整数是否只出现一次,都会给出“true”或“false” 到目前为止,我已经: let one::Eq a=>a->[a]->Bool;一次x l= 但是我还没有完成代码的编写。正如您可能知道的,我对Haskell非常陌生。从使用模式匹配开始: once x [] = once x (y:ys) = 这不会立即为您提供一个好的程序,但会引导您走向正确的方向。从使用模式匹配开始: once x [] = once
但是我还没有完成代码的编写。正如您可能知道的,我对Haskell非常陌生。从使用模式匹配开始:
once x [] =
once x (y:ys) =
这不会立即为您提供一个好的程序,但会引导您走向正确的方向。从使用模式匹配开始:
once x [] =
once x (y:ys) =
这不会立即给你一个好的计划,但它会引导你走向正确的方向。我会像回答家庭作业问题一样回答这个问题,因为它看起来像一个家庭作业问题
阅读函数声明中的模式匹配,特别是当它们给出处理列表的示例时。您将使用稍后提供的工具,但可能您的教授正在教授模式匹配。我将像回答家庭作业问题一样回答这个问题,因为它看起来像一个家庭作业问题
阅读函数声明中的模式匹配,特别是当它们给出处理列表的示例时。您将使用稍后的工具,但您的教授可能正在教授模式匹配。这里有一个解决方案,它不明确使用模式匹配。相反,它会跟踪表示是否已发现事件的
Bool
正如其他人所指出的,这可能是一个家庭作业问题,因此我故意将然后
和其他
分支留空。我鼓励用户3482534尝试使用这段代码并自己填充它们
once :: Eq a => a -> [a] -> Bool
once a = foldr f False
where f x b = if x == a then ??? else ???
编辑:我最初想到的天真实现是:
once :: Eq a => a -> [a] -> Bool
once a = foldr f False
where f x b = if x == a then b /= True else b
但这是不正确的
λ. once 'x' "xxx"
True
当然,这应该是False
,因为'x'
发生了不止一次
但是,为了说明可以使用折叠来编写一次,
,下面是一个修订版,它使用自定义的monoid来跟踪元素出现的次数:
import Data.List
import Data.Foldable
import Data.Monoid
data Occur = Zero | Once | Many
deriving Eq
instance Monoid Occur where
mempty = Zero
Zero `mappend` x = x
x `mappend` Zero = x
_ `mappend` _ = Many
once :: Eq a => a -> [a] -> Bool
once a = (==) Once . foldMap f
where f x = if x == a then Once else Zero
main = do
let xss = inits "xxxxx"
print $ map (once 'x') xss
哪张照片
[False,True,False,False,False]
正如所料
once
的结构与原来的类似,但不完全相同。这里有一个解决方案,它没有明确使用模式匹配。相反,它会跟踪表示是否已发现事件的Bool
正如其他人所指出的,这可能是一个家庭作业问题,因此我故意将然后
和其他
分支留空。我鼓励用户3482534尝试使用这段代码并自己填充它们
once :: Eq a => a -> [a] -> Bool
once a = foldr f False
where f x b = if x == a then ??? else ???
编辑:我最初想到的天真实现是:
once :: Eq a => a -> [a] -> Bool
once a = foldr f False
where f x b = if x == a then b /= True else b
但这是不正确的
λ. once 'x' "xxx"
True
当然,这应该是False
,因为'x'
发生了不止一次
但是,为了说明可以使用折叠来编写一次,
,下面是一个修订版,它使用自定义的monoid来跟踪元素出现的次数:
import Data.List
import Data.Foldable
import Data.Monoid
data Occur = Zero | Once | Many
deriving Eq
instance Monoid Occur where
mempty = Zero
Zero `mappend` x = x
x `mappend` Zero = x
_ `mappend` _ = Many
once :: Eq a => a -> [a] -> Bool
once a = (==) Once . foldMap f
where f x = if x == a then Once else Zero
main = do
let xss = inits "xxxxx"
print $ map (once 'x') xss
哪张照片
[False,True,False,False,False]
正如所料
once
的结构与原始的结构相似,但不完全相同。考虑一个函数,该函数根据是否存在匹配将值映射到1或0
match :: a -> [a] -> [Int]
match x xs = map -- fill in the thing here such that
-- match 3 [1,2,3,4,5] == [0,0,1,0,0]
请注意,sum
函数用于获取数字列表并返回列表中数字的总和。因此,要计算匹配项,函数可以使用match
函数并返回计数
countN :: a -> [a] -> Int
countN x xs = ? $ match x xs
最后是一个函数,它利用countN
函数只检查1的计数<代码>(==1)
希望您能找出其余的…考虑一个函数,它根据匹配的时间将值映射到1或0
match :: a -> [a] -> [Int]
match x xs = map -- fill in the thing here such that
-- match 3 [1,2,3,4,5] == [0,0,1,0,0]
请注意,sum
函数用于获取数字列表并返回列表中数字的总和。因此,要计算匹配项,函数可以使用match
函数并返回计数
countN :: a -> [a] -> Int
countN x xs = ? $ match x xs
最后是一个函数,它利用countN
函数只检查1的计数<代码>(==1)
希望您能找出其余的…您可以筛选列表,然后检查结果列表的长度。如果length==1,则给定整数只出现一次:
once :: Eq a => a -> [a] -> Bool
once x = (== 1) . length . filter (== x)
您可以筛选列表,然后检查结果列表的长度。如果length==1,则给定整数只出现一次:
once :: Eq a => a -> [a] -> Bool
once x = (== 1) . length . filter (== x)
对于一般计数,使用
导入数据.List(foldl')
,无点
count pred = foldl' (\ n x -> if pred x then n + 1 else n) 0
适用类
count (< 10) [1 .. 10] == 9
count (== 'l') "Hello" == 2
高效的O(n)短路谓词形式,测试谓词是否恰好满足一次:
once :: (a -> Bool) -> [a] -> Bool
once pred list = one list 0
where
one [] 1 = True
one [] _ = False
one _ 2 = False
one (x : xs) n | pred x = one xs (n + 1)
| otherwise = one xs n
或者,使用任何:
none pred = not . any pred
once :: (a -> Bool) -> [a] -> Bool
once _ [] = False
once pred (x : xs) | pred x = none pred xs
| otherwise = one pred xs
给予
哪个
对于一般计数,使用导入数据.List(foldl')
,无点
count pred = foldl' (\ n x -> if pred x then n + 1 else n) 0
适用类
count (< 10) [1 .. 10] == 9
count (== 'l') "Hello" == 2
高效的O(n)短路谓词形式,测试谓词是否恰好满足一次:
once :: (a -> Bool) -> [a] -> Bool
once pred list = one list 0
where
one [] 1 = True
one [] _ = False
one _ 2 = False
one (x : xs) n | pred x = one xs (n + 1)
| otherwise = one xs n
或者,使用任何:
none pred = not . any pred
once :: (a -> Bool) -> [a] -> Bool
once _ [] = False
once pred (x : xs) | pred x = none pred xs
| otherwise = one pred xs
给予
哪个
解决更一般的问题通常也更容易。我建议OP定义发生次数::Eq a=>Int->a->[a]->Bool
?@TomEllis在这种情况下,我甚至建议OP定义一个函数发生次数::Eq a=>a->[a]->[a]
,它可以找到列表中元素的每个实例,然后确定它发生了多少次就很简单了。@TomEllis,在这种情况下,这似乎是矫枉过正。有一个标准的Prelude函数可以填充我给出的定义,但OP也可以编写它。@bheklir:当然,甚至count::a->[a]->Int
!解决更一般的问题通常也更容易。我建议OP定义发生次数::Eq a=>Int->a->[a]->Bool
?@TomEllis对于这种情况,我甚至建议OP定义一个函数发生次数