处理haskell元组的好功能和技巧?

too*_*ays 5 haskell types

我最近一直在做元组和元组列表的大量工作,我一直想知道我是否明智.

对我来说,事情感觉尴尬和笨重,这表明我做错了什么.

例如,我编写了三个便利函数,用于获取3个值的元组中的第一个,第二个和第三个值.

有没有更好的方法让我失踪?

是否有更多通用函数可以组合和操作元组数据?

以下是我想要做的一些事情,感觉应该是一般性的.

提取值:我是否需要为大小为二,三,四和五等的元组创建一个版本的fst,snd等...?

fst3(x,_,_) = x
fst4(x,_,_,_) = x
Run Code Online (Sandbox Code Playgroud)

操作值:你可以在一对列表中递增每个元组的最后一个值,然后使用相同的函数来递增三元组列表中每个元组的最后一个值吗?

压缩和解压缩值:有拉链和拉链3.我还需要一个zip4吗?或者是否有某种方法来创建一般的zip功能?

对不起,如果这似乎是主观的,我老实说不知道这是否可能,或者我每次需要一般解决方案时都浪费时间编写3个额外功能.

感谢您提供任何帮助!

ken*_*ytm 8

提取价值

是的,你需要fstN自己写.但为什么不在模式匹配中提取它呢?

压缩和解压缩值

Data.List已经提供了最多zip7.一般情况下zipN,使用ZipList.

请参阅如何在Haskell中压缩多个列表?.

操纵价值观

不是没有扩展.由于所有元组都有不同的类型,因此您必须创建一个类型类,例如:

{-# 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)
Run Code Online (Sandbox Code Playgroud)

然后你可以使用

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)]
Run Code Online (Sandbox Code Playgroud)

(lastOf很相似.)

但为什么不使用单独的功能?

  • 无耻的插头:`Firstable`,`Secondable`,`Thirdable`,......`Nthable`!http://hackage.haskell.org/package/nthable (3认同)

Nor*_*sey 7

当我开始拥有大元组时,我使用Haskell的可怜借口来记录语法,为每个元素命名,例如,

data LatticeOperations a = LO { bot :: a
                              , top :: a
                              , glb :: a
                              , lub :: a
                              , le  :: a
                              }
Run Code Online (Sandbox Code Playgroud)

这是一个五元组,但名称变成了选择单个元素的函数.

对于更改元组,您有记录更新语法.在我刚刚给出的示例中,仅替换一个元素是没有意义的,但我可能会,例如,细化部分顺序并替换三个元素

lattice { le = le', glb = glb', lub = lub' }
Run Code Online (Sandbox Code Playgroud)

当然,如果你有一个很大的记录,并且只是想增加你可以做类似的事情

data FatRecord = FR { count :: Int, ... }

fat = fat { count = count fat + 1 }
Run Code Online (Sandbox Code Playgroud)

我不认为记录语法有助于zip和解压缩.