Haskell ::元组列表的递归

时间:2017-09-12 12:20:57

标签: haskell recursion tuples

我正在映射元组并设法使其适用于单个元组(a,a)。但是当我将元组更改为[[(a, a)]]时,它表示"无法与预期的[(a, a)]类型匹配(a, a)

    mapTuple :: (a -> b) -> [[(a, a)]] -> [(b, b)]
    mapTuple f [] = []
    mapTuple f ((a1, a2) : xs) = (f a1, f a2) : mapTuple f xs

    myfunc :: Int -> Int
    myfunc xk = xk + 1


    myTup = [[(1,2),(5,6),(9,10)]] :: [[(Int, Int)]]
    test = mapTuple myfunc myTup

还没有打破错误。我在这里遗漏了一些东西。在此先感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

当您将类型更改为[[(a,a)]]时,您的mapTuple无法正常工作,因为((a1, a2) : xs)仍然具有[(a,a)]类型。

如果您想将mapTuple应用于元组列表而不是元组列表,那么您根本不需要更改mapTuple。

让我们看一下第二种类型: mapTuple(在更改之前)具有类型(a -> b) -> [(a,a)] -> [(b,b)]

将mapTuple部分应用于myfunc,我们得到[(a,a)] -> [(b,b)]

从评论中您需要一个需要[[(1,1),(2,2)],[(3,3)]] :: [[(a,a)]]并返回[[(2,2),(3,3)],[(4,4)]] :: [[(b,b)]]

的函数

因此,我们希望将此部分功能应用于[(a,a)]中的每个[[(a,a)]]以获取[[(b,b)]]

总的来说,我们想要一个类型为的函数: ([(a,a)] -> [(b,b)]) -> [[(a,a)]] -> [[(b,b)]]

这可以简化为(a -> b) -> [a] -> [b]。那么已经有一个功能可以为我们做到这一点!定期旧地图。

所以使用类型为(a -> b) -> [(a, a)] -> [(b, b)]的旧mapTuple 我们通过以下方式得到正确的结果:

test = map (mapTuple myfunc) myTup

希望这是有道理的,如果不随意要求澄清:)

答案 1 :(得分:1)

这不是您问题的一对一答案。但是我不得不说,在Haskell中,元组不是像(a,a)这样的类型的理想表示。元组用于对不同类型进行分组,例如(a,b)

您的工作基本上需要fmap超过元组,但fmap仅影响元组的第二项。然后,您可以从元组创建一个“新类型”,用于新的仿函数实例,其中fmap将影响这两个项目。但是......你已经拥有了。它是[]。那么,为什么不使用[]代替元组呢?如果你深入了解应用类型,会引入极大的简单性?

mapNestedList :: (a -> b) -> [[[a, a]]] -> [[b, b]]
mapNestedList f = ((map f <$>) =<<)

Prelude> mapNestedList (+1) [[[1,2],[5,6],[9,19]]]
[[2,3],[6,7],[10,20]]

那么这里发生了什么?

  • map (+1)的类型为Num a => [a] -> [a]
  • 记住<$>实际上是内联fmap(map (+1) <$>)的类型为(Num a, Functor f) => f [a] -> f [a]
  • 这意味着我们有一个包含列表的仿函数,我们将函数应用于这些列表。这个仿函数可以是Maybe类型或其他类型。在这种特殊情况下,我们的仿函数碰巧是另一个[]
  • 然后是(=<<)运算符,它实际上是monadic bind (>>=)的翻转版本。 (=<<)的类型为Monad m => (a -> m b) -> m a -> m b。对于此类型签名,在此特定情况下,a类型变量代表类似Num c => [[c]]的类型,而b代表Num c => [c],产生m b解析为Num c => [[c]]m a以解析为Num c => [[[c]]]
  • 因此,从上面给出(a -> m b)的类型变量,我们可以使用((map (+1) <$>),最终类型((map (+1) <$>) =<<)原来是(Num b, Monad m) => m (m [b]) -> m [b]

再次......

Prelude> mapNestedList (+1) [[[1,2],[5,6],[9,19]],[[10,20],[30,40]]]
[[2,3],[6,7],[10,20],[11,21],[31,41]]