我试图为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]
还有另一种链接咖喱参数的方法吗?
答案 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)
let
和where
子句都是递归计算的,所以你可以这样:
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(filename
,1
以及下一个名为Dimentions
)的函数返回的内容等等。这根本不是你想要的。
.
运算符以(f . g)(x)
的数学方式将两个函数连接在一起,相当于f(g(x))
。而且,这与您在此处创建的内容没有任何相似之处。