Each op `foo :: ...` now has a corresponding `foo' :: OpParams -> ...`
which lets you set optional attributes. `OpParams` is currently a type alias for
`OpDef -> OpDef`. In the future we should consider more type safety, e.g.,
using type-level strings and OverloadedLabels for optional attributes.
I used it to replace a few manual `buildOp`s in our code with the codegenerated
ops, now that it's easier to set attributes. I also removed `tensorAttr` and
`named` since it's now possible to set those op attributes directly.
Although this clutters up the API a bit, I think it's simpler than using type
classes to implement optional arguments (as in, for example, `Text.Printf`) --
especially in terms of type inference with the rest of the library.
This change adds a class that both `Build` and `Session` are instances of:
class MonadBuild m where
build :: Build a -> m a
All stateful ops (generated and manually written) now have a signature that returns
an instance of `MonadBuild` (rather than just `Build`). For example:
assign_ :: (MonadBuild m, TensorType t)
=> Tensor Ref t -> Tensor v t -> m (Tensor Ref t)
This lets us remove a bunch of spurious calls to `build` in user code. It also
lets us replace the pattern `buildAnd run foo` with the simpler pattern `foo >>= run`
(or `run =<< foo`, which is sometimes nicer when foo is a complicated expression).
I went ahead and deleted `buildAnd` altogether since it seems to lead to
confusion; in particular a few tests had `buildAnd run . pure` which is
actually equivalent to just `run`.