Haskell 中不带括号的链接参数

Chaining parameters without parentheses in Haskell

我正在尝试为 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]

是否有另一种链接柯里化参数的方法?

当然可以。 $ 在这种情况下的问题在于它是右结合的:

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])
           )

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 是一个类型构造函数,它接受 一个 参数,该类型由 FileInfo 类型返回,预计需要三个参数(filename1 以及下一个名为 Dimentions) 的函数返回的任何内容,依此类推。这根本不是你想要的。

. 运算符以数学方式将两个函数连接在一起 (f . g)(x) 等同于 f(g(x))。再一次,这与您在此处尝试创建的内容完全不同。