繁体   English   中英

Haskell递归后返回单个元组

[英]Haskell return single tuple after recursion

我在玩.bmp图像和ascii艺术,遇到了一个有关模式匹配和元组递归的问题。

该函数只需要简单地将单词列表转换为整数即可。在不改变高度和宽度的情况下。 我的尝试:

convertToIntegers :: ([GHC.Word.Word8], Integer, Integer) -> ([Integer], Integer, Integer)
convertToIntegers ([], x, y) =  ([], x, y)
convertToIntegers ((a:as), x, y) = ( toInteger a : convertToIntegers (as, x, y), x, y)

显然,这不起作用并返回类型错误:

Couldn't match expected type `[Integer]' with actual type `([Integer], Integer, Integer)'

In the return type of a call of `convertToIntegers' 
In the second argument of `(:)', namely `convertToIntegers (as, x, y)'
In the expression: toInteger a : convertToIntegers (as, x, y)

看起来应该很简单,我可以通过拆分并使用辅助函数来完成它。 为了弄清楚这一点,我尝试了以下方法:

convertToIntegers :: ([GHC.Word.Word8], Int, Int) -> [Integer]
convertToIntegers ([], x, y) =  []
convertToIntegers ((a:as), x, y) = toInteger a : convertToIntegers (as, x, y)

这很好。 因此,问题在于,我根本不知道在操作其中的列表时如何返回单个元组。 真是烦我,有人可以帮忙吗?

为什么不只是使用地图?

convertToIntegers :: ([GHC.Word.Word8], Integer, Integer) -> ([Integer], Integer, Integer)
convertToIntegers (as, x, y) = (map toInteger as, x, y)

编辑:

您的主要问题是这里有一个实际的错误:

( toInteger a : convertToIntegers (as, x, y), x, y)
                                    ^  ^  ^

您正在返回一个元组作为另一个元组的第一个参数,在类型签名中您声称要返回一个整数列表。 如果您不想使用地图,则可以这样编写:

convertToIntegers :: ([GHC.Word.Word8], Integer, Integer) -> ([Integer], Integer, Integer)
convertToIntegers (as, x, y) = (convertWords as, x, y)
    where
        convertWords [] = []
        convertWords (z:zs) = toInteger z : convertWords zs

编写此使用模式的标准方法是let

convertToIntegers :: ([GHC.Word.Word8], Integer, Integer) -> ([Integer], Integer, Integer)
convertToIntegers ([], x, y) =  ([], x, y)
convertToIntegers ((a:as), x, y) = let (rs, x2, y2) = convertToIntegers (as, x, y)
                                   in  (toInteger a : rs, x2, y2)

Haskell的let是递归的; 如果要在let的定义的两侧使用x,y ,则将阴影外部名称x,y (阻止对它们的访问)。 这样x,y方程式RHS上的x,y引用了LHS上的外部参数x,y ,而LHS上的x2,y2用于传递从内部函数调用返回的值。

这并不意味着将返回值之前进行此调用。 恰恰相反,由于Haskell的懒惰,首先构造带有孔(_1, _2, _3)的返回值(三元组(_1, _2, _3) ,只有在访问这些孔时,才根据定义触发进一步的评估,其中_1 = toInteger a : rs_2 = x2_3 = y2 因此,如果该访问为head _1 ,则不会触发任何函数调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM