处理haskell元组的好函数和技术?
我最近做了很多关于元组和元组列表的工作,我一直在想我是否明智 事情让我感到尴尬和笨拙,这对我来说意味着我做错了什么 例如,我编写了三个方便函数,用于获取3个值的元组中的第一个、第二个和第三个值 有没有更好的方法让我错过 是否有更通用的函数允许您编写和操作元组数据 以下是我正在尝试做的一些事情,这些事情应该是可以推广的 提取值: 我需要创建fst、snd等的版本吗。。。对于大小为2、3、4和5的元组,等等处理haskell元组的好函数和技术?,haskell,types,Haskell,Types,我最近做了很多关于元组和元组列表的工作,我一直在想我是否明智 事情让我感到尴尬和笨拙,这对我来说意味着我做错了什么 例如,我编写了三个方便函数,用于获取3个值的元组中的第一个、第二个和第三个值 有没有更好的方法让我错过 是否有更通用的函数允许您编写和操作元组数据 以下是我正在尝试做的一些事情,这些事情应该是可以推广的 提取值: 我需要创建fst、snd等的版本吗。。。对于大小为2、3、4和5的元组,等等 fst3(x,_,_) = x fst4(x,_,_,_) = x 操纵值: 您可以增加成
fst3(x,_,_) = x
fst4(x,_,_,_) = x
操纵值:
您可以增加成对列表中每个元组的最后一个值,然后使用相同的函数增加三元组列表中每个元组的最后一个值吗
压缩和解压缩值:
有一个拉链和一个拉链。我也需要拉链吗?或者有没有办法创建一个通用的zip函数
抱歉,如果这看起来很主观,我真的不知道这是否可能,或者每次我需要一个通用的解决方案时,我是否在浪费时间编写3个额外的函数
谢谢你能给予的任何帮助 如果不使用模板Haskell之类的扩展,就无法概括元组大小。所以,如果我们只考虑Haskell:是的,你确实需要编写<代码> fST <代码>等版本。对于每个元组大小,不,你不能编写一般的zip方法。提取值 是的,您需要自己编写
fstN
。但是为什么不在模式匹配中提取呢
压缩和解压缩值
已提供多达zip7
。对于常规zipN
,请使用ZipList
看
操纵值
没有扩展就不行。由于所有元组的类型不同,因此必须创建一个类型类,例如:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}
class Firstable a b c | a -> b, a -> c where
firstOf :: a -> b
restOf :: a -> c
concatenate :: b -> c -> a
instance Firstable [a] a [a] where
firstOf = head
restOf = tail
concatenate = (:)
instance Firstable (a,b) a b where
firstOf = fst
restOf = snd
concatenate = (,)
instance Firstable (a,b,c) a (b,c) where
firstOf (x,_,_) = x
restOf (_,x,y) = (x,y)
concatenate x (y,z) = (x,y,z)
instance Firstable (a,b,c,d) a (b,c,d) where
firstOf (x,_,_,_) = x
restOf (_,x,y,z) = (x,y,z)
concatenate x (y,z,w) = (x,y,z,w)
instance Firstable (a,b,c,d,e) a (b,c,d,e) where
firstOf (x,_,_,_,_) = x
restOf (_,x,y,z,w) = (x,y,z,w)
concatenate x (y,z,w,t) = (x,y,z,w,t)
那你可以用
incFirst :: (Num b, Firstable a b c) => a -> a
incFirst x = (1 + firstOf x) `concatenate` restOf x
main = do
print $ map incFirst [(1,2),(3,4),(5,6)]
print $ map incFirst [(1,3,6,7),(2,5,-2,4)]
(lastOf
类似。)
但是为什么不使用单独的函数呢?Haskell内置的
fst
和snd
只支持元组对,所以您可以定义自己的元组对。如果要增加列表中的最后一个值,请反转列表,从该端开始工作,然后将其反转回来。如果希望该增量适用于列表和元组列表,只需定义一个新函数,该函数将为这些数据类型进行增量,并在列表的增量函数中调用该函数@肯尼特回答了zipN的问题
在Haskell中使用列表和元组与许多语言有点不同,但经过一段时间后,它们相比起来感觉特别自然和强大。一旦元组的大小超过3左右,和/或相同的元组类型得到广泛使用,最好使用记录。当我开始使用大元组时,我使用Haskell的记录语法的可怜借口为每个元素命名,例如
data LatticeOperations a = LO { bot :: a
, top :: a
, glb :: a
, lub :: a
, le :: a
}
这是一个五元组,但是名称变成了选择单个元素的函数
对于更改元组,您有记录更新语法。在我刚刚给出的示例中,只替换一个元素是没有意义的,但是我可以,例如,改进偏序并替换三个元素
lattice { le = le', glb = glb', lub = lub' }
当然,如果你有一个大的记录,只是想增加你可以做一些事情,如
data FatRecord = FR { count :: Int, ... }
fat = fat { count = count fat + 1 }
我不认为记录语法有助于压缩和解压缩。我最近发现
{-#语言记录通配符}
允许记录将字段选择器用作值-
这样地:
数据R=R{a::Int,b::String,c::Bool}
testA R{..}=a>0
或
.. = R{..}式中a=7;b=“x”;c=真
检查GHC手册 迟到总比不迟到好:试试。对不起,我不清楚我的意思(我已经更正了这个问题)。我的意思不是:你能增加成对列表的最后一个值,然后用同样的函数增加三元组列表的最后一个值吗?我的意思是:你能增加成对列表中每个元组的最后一个值,然后使用相同的函数增加三元组列表中每个元组的最后一个值吗?抱歉搞混了!创建5+个函数来做完全相同的事情对我来说似乎是浪费。(并不是说我在必要时做这件事有任何问题)。也许我只是喜欢非常干燥的东西。我想可能做得太过分了。无耻的插拔:
Firstable
,Secondable
,Thirdable
<代码>n表!这是因为元组的每个大小都是不同的类型。在类型系统中不可能只说“一个元组”,因为没有这样的类型-有对、3元组和4元组,它们都是不同的东西。