我正在尝试在Haskell中编写一个函数,它将4个整数作为输入,并计算有多少输入数等于第一个整数。
例如:
howManyEq 3 4 5 6 returns 0
howManyEq 3 4 3 5 returns 2
howManyEq 3 4 3 3 returns 3
howManyEq 3 3 3 3 returns 4
这是我到目前为止创建的函数,当没有输入匹配第一个整数时,它适用于第一个实例。但是当有其他匹配的整数时,它不计算前3个,它总是少计算一个。
howManyEq :: Int -> Int-> Int -> Int -> Int
howManyEq a b c d = count (head (toList a b c d)) (tail (toList a b c d))
count :: Int -> [Int] -> Int
count x [] = 0
count x (y:ys)
| x == y = 1 + (count x ys)
| otherwise = count x ys
toList :: Int -> Int-> Int -> Int -> [Int]
toList a b c d = [a,b,c,d]
我的功能给了我:
howManyEq 3 4 5 6 returns 0
howManyEq 3 4 3 5 returns 1
howManyEq 3 4 3 3 returns 2
howManyEq 3 3 3 3 returns 3
当其他输入整数相等时,我不确定如何计算第一个整数。
答案 0 :(得分:1)
Your count
function counts the number of equal elements in the remainder of the "list". If that number is zero, your teacher wants the result to be zero. If there is one or more, it returns the amount counted in the remainder of the list, but since there is already one element in the head of the list, you should do +1. You can do this by implementing a helper function:
fix :: (Eq a, Num a) => a -> a
fix 0 = 0
fix n = n+1
Now you can simply pass the result of your count
function through fix
:
howManyEq :: Int -> Int-> Int -> Int -> Int
howManyEq a b c d = fix $ count (head (toList a b c d)) (tail (toList a b c d))
count :: Int -> [Int] -> Int
count x [] = 0
count x (y:ys)
| x == y = 1 + (count x ys)
| otherwise = count x ys
toList :: Int -> Int-> Int -> Int -> [Int]
toList a b c d = [a,b,c,d]
additional advice:
You use head (toList a b c d)
in your call to count. But you already know in advance that this is a
, so omit this.
The same with the tail: simply only feed the last three arguments, so: toList b c d
.
Use the most generic type signature possible: for toList :: a -> a -> a -> [a]
(given the previous fix), for count :: (Eq a, Num b) => a -> [a] -> b
, and for howManyEq :: (Eq a, Eq b, Num b) => a -> a -> a -> a -> b
.
If you define the same thing multiple time, you can use a where t = ...
clause, like where cys = count x ys
This would result in something like:
fix :: (Eq a, Num a) => a -> a
fix 0 = 0
fix n = n+1
howManyEq :: (Eq a, Eq b, Num b) => a -> a -> a -> a -> b
howManyEq a b c d = fix $ count a $ toList b c d
count :: (Eq a, Num b) => a -> [a] -> b
count x [] = 0
count x (y:ys)
| x == y = 1 + cys
| otherwise = cys
where cys = count x ys
toList :: a -> a -> a -> [a]
toList a b c = [a,b,c]
答案 1 :(得分:-1)
Here's one way:
{-# LANGUAGE TypeFamilies #-}
class HowManyEq a where
howManyEq' :: Int -> Int -> Int -> a
instance HowManyEq Int where
howManyEq' count x y = count + fromEnum (x == y)
{-# INLINE howManyEq' #-}
instance (HowManyEq a, b ~ Int) => HowManyEq (b -> a) where
howManyEq' count x y b = (howManyEq' $! count + fromEnum (b == x)) x y
{-# INLINE howManyEq' #-}
howManyEq :: HowManyEq a => Int -> Int -> a
howManyEq = howManyEq' 0
howManyEq4 :: Int -> Int -> Int -> Int -> Int
howManyEq4 x y z w =
case howManyEq x y z w of
0 -> 0
n -> n + 1