所以我试图在Haskell中定义一个函数,如果给定一个整数和一个整数列表,无论整数只出现一次,都会给出"true"或"false"。
到目前为止,我已经得到了:
let once :: eq a => a ->[a] -> Bool; once x l =
但是我还没有写完代码。我对Haskell很陌生,你可能知道。
首先使用模式匹配:
once x [] =
once x (y:ys) =
这不会立即给你一个好的程序,但它会引导你朝着正确的方向前进。
这是一个不显式使用模式匹配的解决方案。相反,它会跟踪表示是否已找到事件的Bool
。
正如其他人指出的那样,这可能是一个家庭作业问题,所以我故意将then
和else
分支留空。我鼓励user3482534尝试使用此代码并自行填写。
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'
发生不止一次。
但是,为了表明可以使用折叠来编写once
,下面是一个修订版本,它使用自定义幺半群来跟踪元素出现的次数:
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
的结构与原始结构相似,但不完全相同。
我会像家庭作业问题一样回答这个问题,因为它看起来像一个。
阅读有关函数声明中的模式匹配的信息,尤其是当它们给出处理列表的示例时。 您稍后将使用 Data.List 中的工具,但您的教授可能正在教授模式匹配。
考虑一个将值映射到 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,则给定整数只出现一次:
once :: Eq a => a -> [a] -> Bool
once x = (== 1) . length . filter (== x)
用于一般计数,用import Data.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
给
once pred xs = count pred xs == 1
高效的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
或者,使用 any
:
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
给
elemOnce y = once (== y)
哪
elemOnce 47 [1,1,2] == False
elemOnce 2 [1,1,2] == True
elemOnce 81 [81,81,2] == False