I have this code :
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
Which is a Haskell translation of this :
https://www.codewars.com/kata/length-of-missing-array
Now it works, however I have two issues :
I would like to have getMissing just be :
getMissing :: [[Int]] -> Int
And then just use that function inside of the other one, but I don't know how to utilize that function on the Maybe
of a Maybe
.
Second, I tried simply doing :
getMissing :: Eq a => [Maybe [a]] -> Maybe Int
getLengthOfMissingArray :: Eq a => Maybe [Maybe [a]] -> Maybe Int
But then Haskell generates errors when I try to use QuickCheck on test cases like :
getLengthOfMissingArray (Just [ Nothing, Just [ 4, 5, 1, 1 ], Just [ 1 ],
Just [ 5, 6, 7, 8, 9 ] ]) `shouldBe` Nothing
That works, but this generates type errors :
getLengthOfMissingArray (Just [Just []]) `shouldBe` Nothing
I guess without an actual a
there there's an issue because if I just try to run it on a Nothing
it also generates the same type error:
"Ambiguous type variable 'a0' arising from a use of 'getLengthOfMissingArray' prevents the constraint '(Eq a0)' from being solved."
sequence :: [Maybe a] -> Maybe [a]
will help you adapt your [Maybe [Int]]
to [[Int]]
.
join :: Maybe (Maybe a) -> Maybe a
might also be useful.
Both sequence and join have more general types - I wrote them as I expect you will use them here.
You will see "Ambiguous type variable" errors when you pass a polymorphic value to a function that is polymorphic in its argument. To actually run the function GHC needs to use a specific type, and it won't choose - you need to. Since you want getLengthOfMissingArray
to remain polymorphic, you can add a type signature to the test case to specify how the tests should run.
Thanks to bergey (and dramforever on cw) :
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
And adjusting the tests :
getLengthOfMissingArray (Nothing :: Maybe [Maybe [Int]]) `shouldBe` Nothing
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.