【问题标题】:Haskell: Transposition on a list of stringsHaskell:在字符串列表上转置
【发布时间】:2016-05-01 02:47:11
【问题描述】:

Haskell 的新手,到目前为止,这门语言很有趣。我希望得到一个好的提示而不是答案,因为我正在享受 Haskell 的思维改变。

问题:我有一个字符串列表,我想转置它们。

let x = ["hello", "world"]

会变成

["hw", "eo", "lr", "ll", "od"]

到目前为止,我所拥有的是:

   transposeString :: [a] -> [a]
   transposeString ([]:_) = []
   transposeString x = (map head x) : transposeString (map tail x)

我肯定知道类型签名有问题。我的理由是

Let y = ["wow", "top"]
map head y 

返回“wt”,所以在列表的其余部分递归它会起作用吗?

提前感谢您的任何提示。

【问题讨论】:

  • 关于类型签名,考虑[a] -> [a]包含[Int] -> [Int]。做 transposeString [1,2,3] 有意义吗?

标签: haskell recursion


【解决方案1】:

请注意,您不必提供类型签名:Haskell 编译器可以派生一个。如果你把你的实现放在一个文件中:

transposeString ([]:_) = []
transposeString x = (map head x) : transposeString (map tail x)

ghci中用:t查询类型,返回:

*Main> :t transposeString 
transposeString :: [[b]] -> [[b]]

这很有意义:

  1. 您转置了一个矩阵,它是一个列表列表。 [[b]]b 元素列表的列表;和
  2. 您可以自己从实现中派生它:map head x 表示x元素 必须是一个列表([b]),因为我们执行映射,我们必须嵌套列表一个额外的级别,所以[[b]]tail 也是如此。

据我所知,您的实现是正确的。您可以通过说 [b] ~ String 来对其进行专门化,从而为 Strings 添加类型签名:

transposeString :: [String] -> [String]
transposeString ([]:_) = []
transposeString x = (map head x) : transposeString (map tail x)

这又是有道理的,因为String ~ [Char] 因此b ~ Char。但是特化一个函数类型并没有多大意义:你最好总是使用最通用的类​​型签名。在这种情况下[[b]] -> [[b]]

【讨论】:

  • 谢谢!这行得通!我仍然无法让它适用于我的特殊情况(下面的帖子中的 cmets),但这回答了我的问题。
【解决方案2】:

注意一点。 tranposeString 的类型签名允许接受平面列表作为参数。转置[String] 有效,因为[String]s 实际上只是[[Char]]s,但是当您尝试在[Int] 上调用transposeString 时会发生什么?毕竟,类型签名允许这样做。

在旁注中,我问你,鉴于你当前的功能,如果你调用 transposeString [] 会发生什么?

【讨论】:

  • 另一个有趣的案例是transposeString ["hello", "mars"],分几步就涉及到["o", ""]
  • 这是一个空列表的无限递归。我也在努力!哈哈。这是更大程序中的一个小功能。 Chi 的观点正是我现在正在研究的,因为我遇到了 ["ABCD", "EFGH", "IJKL" ..."YZ"] 的情况,每个字符串中有 4 个字符,但最后一个字符除外。它引发异常,我假设是惰性评估。
  • 踢的示例输出:[],[],[],[],[],[],[],[],[],[],[],[],[ ],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[], [],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[] ,[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[ ],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[], []^Z,[] [1]+ 停止 ghci
【解决方案3】:

请记住String[Char]

"abc" == 'a' : 'b' : 'c' : []

从这里您可以使用列表的可遍历性:

transpose :: [[a]] -> [[a]]
transpose mat = getZipList $ sequenceA $ map ZipList mat

test' = transpose [[1,2,3],[4,5,6],[7,8,9]] -- == [[1,4,7],[2,5,8],[3,6,9]]
test'' = transpose ["abc", "deg", "klm"] -- == ["adk","bel","cgm"]

您还可以在 haskell 文档中检查 transponse 的默认实现 https://hackage.haskell.org/package/base-4.12.0.0/docs/src/Data.OldList.html#transpose

transpose               :: [[a]] -> [[a]]
transpose []             = []
transpose ([]   : xss)   = transpose xss
transpose ((x:xs) : xss) = (x : [h | (h:_) <- xss]) : transpose (xs : [ t | (_:t) <- xss])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多