Haskell Maybe /参数多态

时间:2018-10-15 00:33:49

标签: haskell

我有此代码:

getLengthOfMissingArray :: Maybe [Maybe [Int]] -> Maybe Int 
getLengthOfMissingArray maybelist = do
  ns <- maybelist 
  getMissing ns

getMissing :: [Maybe [Int]] -> Maybe Int 
getMissing maybelist
  | any (==Nothing) maybelist = Nothing
  | any (==Just []) maybelist = Nothing
  | otherwise                 = Just (sumn mx - sumn (mn - 1) - sum l0)
  where
    l0 = map length (catMaybes maybelist)
    (mn,mx) = (minimum l0, maximum l0)
    sumn n = n * (n + 1) `quot` 2

这是Haskell的译文:

https://www.codewars.com/kata/length-of-missing-array

现在可以了,但是我有两个问题:

  • 有点笨
  • 它应该在任何列表上工作,而不仅仅是int的

我想让getMissing成为:

getMissing :: [[Int]] -> Int 

然后仅在另一个函数中使用该函数,但我不知道如何在Maybe的{​​{1}}上使用该函数。

第二,我尝试简单地做:

Maybe

但是,当我尝试在测试用例上使用QuickCheck时,Haskell会生成错误:

getMissing :: Eq a => [Maybe [a]] -> Maybe Int 
getLengthOfMissingArray :: Eq a => Maybe [Maybe [a]] -> Maybe Int 

可以,但是会产生类型错误:

getLengthOfMissingArray (Just [ Nothing, Just [ 4, 5, 1, 1 ], Just [ 1 ],
                                Just [ 5, 6, 7, 8, 9 ] ])     `shouldBe` Nothing

我猜没有实际的getLengthOfMissingArray (Just [Just []]) `shouldBe` Nothing 会有一个问题,因为如果我只是尝试在a上运行它,还会产生相同的类型错误:

  

”由于使用了“ getLengthOfMissingArray”而产生的歧义类型变量“ a0”         阻止解决约束“(Eq a0)”。”

2 个答案:

答案 0 :(得分:4)

sequence :: [Maybe a] -> Maybe [a]将帮助您使[Maybe [Int]]适应[[Int]]

join :: Maybe (Maybe a) -> Maybe a也可能有用。

sequencejoin都有更通用的类型-我写了它们,因为我希望您在这里使用它们。

当您将多态值传递给参数中具有多态性的函数时,您将看到“歧义类型变量”错误。要实际运行GHC功能,需要使用特定的类型,而它不会选择-您需要。由于您希望getLengthOfMissingArray保持多态,因此可以在测试用例中添加类型签名以指定测试的运行方式。

答案 1 :(得分:0)

感谢伯吉(以及cw上的dramforever):

getLengthOfMissingArray :: Eq a => Maybe [Maybe [a]] -> Maybe Int 
getLengthOfMissingArray maybelist = do
  list  <- maybelist 
  ns    <- sequence list 
  getMissing ns

getMissing :: Eq a => [[a]] -> Maybe Int 
getMissing list
  | any (==0) l0  = Nothing
  | otherwise     = Just $ sumn mx - sumn (mn - 1) - sum l0
  where
    l0 = map length list
    (mn,mx) = (minimum l0, maximum l0)
    sumn n = n * (n + 1) `quot` 2

并调整测试:

getLengthOfMissingArray (Nothing :: Maybe [Maybe [Int]]) `shouldBe` Nothing