Is there any syntax for non-recursive binding in Haskell, like the difference between `let` and` let rec` in similar languages?
Non-recursive binding allows me to shadow bound value like:
b a = let norec a = a + 10 in a
here let norec
, created by me means binding let
, but not recursive.
This is very useful when using wildcards:
data MyRecord = MyRecord{ {- vary huuuuuge set of definitions -} }
foo MyRecord{..} = let norec field1 = field1 + 1
field2 = modify field2
{- some other modifications to the fields -}
in MyRecord{..}
Is this achievable? Or how do you deal with it in your business?
source to share
Are these wildcards really useful? The usual old way of doing things looks pretty concise to me:
foo r = r { field1 = field1 r + 1, field2 = modify (field2 r) }
The direct answer to your question is that there is no non-recursive counterpart in Haskell let
; although you can use a monad Identity
to hack something into place:
foo MyRecord{..} = runIdentity $ do
field1 <- return (field1 + 1)
field2 <- return (modify field2)
return MyRecord{..}
source to share
is there any syntax for non-recursive binding in Haskell
No, there is no way to refer to a previously defined variable of a given name when defining a new variable with the same name.
foo MyRecord{..} = let norec field1 = field1 + 1
field2 = modify field2
{- some other modifications to the fields -}
in MyRecord{..}
This can be achieved by writing the modified fields explicitly (while still preserving the immutable characters with a wildcard). Since you don't need local variables, this is not code yet:
foo MyRecord{..} =
MyRecord {
field1 = field1 + 1,
field2 = modify field2,
..
}
Note that here the identifier to the left of the equal sign is the record label, not a variable, and to the right is a variable, so while this looks recursive, it is not.
source to share
Not an answer to your question, but I would like to point out an alternative to lens . Lenses are really a pretty good solution to Haskell's notation problems, which get quite a pain with large data definitions and which RecordWildcards
, alas, don't really fix as well as we would like.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Lens.TH (makeLenses)
data MyRecord = MyRecord{ _field1 :: ...
, _field2 :: ...
{- note the underscores -} }
makeLenses ''MyRecord
foo = (field1 %~ (+1))
. (field2 %~ modify)
. ...
source to share
One of the options:
-- also available from the lens package
(&) :: a -> (a->b) -> b
(&) = flip ($)
f a = -- let norec a = a + 1 in a+a
(a+1) & \a -> a + a
g x = -- let norec x = x+1 in
(x+1) & \x ->
-- let norec x = x+x in
(x+x) & \x ->
-- 1000+x
1000+x
Not very elegant, but at least it is laconic. It also generates several "shading" warnings.
source to share