I'm trying to write a convenience wrapper for hnetcdf
library. Instead of dealing with its low-level interface, I want to be able to describe NetCDF file structure in a simple declarative manner. To achieve this I've created a bunch of ADTs:
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]
They work if I use them like in the following example:
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])
...
but I really dislike extra parenthesis. I tried to use ($)
and (.)
, but with no luck:
-- No way.
let info = Info $ FileInfo filename 1
$ Dimentions [dimX, dimY, dimZ]
$ Variables [var1, var2]
Is there another way to chain curried parameters?
Sure. The problem of $
in this case is that it's right 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])
)
)
So all you need is an operator that's left associative:
($<) :: (a -> b) -> a -> b
($<) = ($)
infixl 0 $< -- left associative
Now the parentheses are correct:
let info = Info $< FileInfo filename 1
$< Dimentions [dimX, dimY, dimZ]
$< Variables [var1, var2]
= (
(
(Info
(FileInfo filename 1)
)
(Dimentions [dimX, dimY, dimZ])
)
(Variables [var1, var2])
)