在Haskell上定义一个布尔函数,用于确定元素是否在列表中出现一次

时间:2014-04-01 17:18:34

标签: haskell

所以我试图在Haskell中定义一个函数,如果给定一个整数和一个整数列表,它将给出一个真正的'或者' false'整数是否只出现一次。

到目前为止,我已经:

  

let once :: Eq a => a - > [a] - > BOOL;一旦x l =

但我还没有写完代码。我可以告诉你,我对Haskell很新。

6 个答案:

答案 0 :(得分:6)

使用模式匹配开始:

once x [] =
once x (y:ys) = 

这不会立即给你一个好的程序,但它会引导你朝着正确的方向前进。

答案 1 :(得分:1)

这是一个不明确使用模式匹配的解决方案。相反,它会跟踪Bool,表示是否已找到发生。

正如其他人所指出的,这可能是一个家庭作业问题,因此我故意将thenelse分支留空。我鼓励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,这里是一个修订版本,它使用自定义的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的结构与原始结构相似但不完全相同。

答案 2 :(得分:0)

我会回答这个问题,好像这是一个家庭作业问题,因为它看起来像是一个。

阅读函数声明中的模式匹配,特别是当它们给出处理列表的示例时。您稍后会使用Data.List中的工具,但您的教授可能正在教授模式匹配。

答案 3 :(得分:0)

考虑将值映射到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)

希望你能弄明白其余的......

答案 4 :(得分:0)

您可以过滤列表,然后检查结果列表的长度。如果length == 1,则只有一次给定的Integer:

once :: Eq a => a -> [a] -> Bool
once x = (== 1) . length . filter (== x)

答案 5 :(得分:0)

通常使用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