在Haskell中没有括号的链接参数

时间:2015-11-16 11:36:13

标签: haskell operator-precedence currying

我试图为hnetcdf库编写一个便利包装器。我希望能够以简单的声明方式描述NetCDF文件结构,而不是处理它的低级接口。为实现这一目标,我创建了一系列ADT:

data Info = Info FileInfo Dimentions Variables
data FileInfo   = FileInfo String Int
data Dimentions = Dimentions [Dimention]
data Variables  = Variables [Variable]
data Dimention  = BoundedDimention String Int | UnboundedDimention String
data Variable   = Variable String Int NC.NcType [Dimention]

如果我使用它们,它们会起作用,如下例所示:

writeNetCDF :: FilePath -> IO ()
writeNetCDF filename = do
    let dimX, dimY, dimZ = ...
    let var1, var2       = ...
    let info = Info (FileInfo filename 1)
                    (Dimentions [dimX, dimY, dimZ])
                    (Variables  [var1, var2])
    ...

但我真的不喜欢额外的括号。我尝试使用($)(.),但没有运气:

    -- No way.
    let info = Info $ FileInfo filename 1
                    $ Dimentions [dimX, dimY, dimZ]
                    $ Variables  [var1, var2]

还有另一种链接咖喱参数的方法吗?

2 个答案:

答案 0 :(得分:4)

不确定。在这种情况下$的问题在于它是正确的关联:

let info = Info $ FileInfo filename 1
                $ Dimentions [dimX, dimY, dimZ]
                $ Variables  [var1, var2]
         = Info ( FileInfo filename 1
                  ( Dimentions [dimX, dimY, dimZ]
                    ( Variables  [var1, var2])
                  )
                )

所以你需要的只是一个左关联的运算符:

($<) :: (a -> b) -> a -> b
($<) = ($)

infixl 0 $< -- left associative

现在括号是正确的:

let info = Info $< FileInfo filename 1
                $< Dimentions [dimX, dimY, dimZ]
                $< Variables  [var1, var2]
         = (
            (
             (Info 
               (FileInfo filename 1)
             )
             (Dimentions [dimX, dimY, dimZ])
            )
            (Variables  [var1, var2])
           )

答案 1 :(得分:0)

letwhere子句都是递归计算的,所以你可以这样:

where
    info = Info f dim vars
    f = FileInfo filename 1
    dim = Dimentions [dimX, dimY, dimZ]
    vars = Variables [var1, var2]

$运算符和.运算符用于创建新函数。因此表达如下:

info = Info $ FileInfo filename 1
            $ Dimentions [dimX, dimY, dimZ]
            $ Variables  [var1, var2]

表示Info是一个Type构造函数,它接受一个参数,FileInfo类型返回一个类型,该类型需要三个agruments(filename1以及下一个名为Dimentions)的函数返回的内容等等。这根本不是你想要的。

.运算符以(f . g)(x)的数学方式将两个函数连接在一起,相当于f(g(x))。而且,这与您在此处创建的内容没有任何相似之处。