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?

+3


source to share


4 answers


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{..}

      

+9


source


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.

+4


source


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

      

+3


source


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.

0


source







All Articles