- Join over
**1.5M+ people** - Join over
**100K+ communities** - Free
**without limits** - Create
**your own community**

@lambdageek how do I reuse generic implementations for functorised ASTs?

ie:

```
data Expr a = Var a (Name (Expr a))
| Other Constructors
```

I'd like `Alpha`

to ignore the annotations (a). However, writing a manual implementation to the class is tedious (given there are 6 methods that need to be written) if I only need to change 1-2 cases. Is there a way to default to the generic implementation in other cases?

Hey, sorry I didn't notice your message @xldenis . All the methods have default implementations provided that `Expr a`

is an instance of `Generic`

, so you can just change the ones you want. If you want to call down to the generic impl, you would need to do something like

`(GHC.Generics.to . gopen ctx pat . GHC.Generics.from) subTerm`

The various `g*`

functions are defined in `Unbound.Generics.LocallyNameless.Alpha`

. If you can stand a newtype, what I usually do is something like

```
newtype Annot a = Annot {getAnnot :: a }
deriving ({- everything -})
```

and then write an instance for `Annot a`

that just uses `(==)`

and `compare`

and is the identity for functions like `open`

and `close`

and then populate your AST with `Annot a`

values

@Ptival you can think of the type of

`fv`

as `(Alpha a, Typeable b) => Fold a (Name b)`

in the sense of the lens libary's Fold. What that means, roughly is that given some syntax structure `a`

(which is an instance of `Alpha`

) you can use `fv`

to iterate over free variables `Name b`

that occur within it and summarize them using some kind of `Monoid`

very similar to how the `Foldable`

typeclass works. More concretely, if you have some `Expr`

type that has variables of type `Name Expr`

in it, you can do `toListOf fv :: Expr -> [Name Expr]`

(using the definition of `toListOf`

from `lens`

, or the one in `Unbound.Generics.LocallyNameless.Internal.Fold`

) more generally `foldMapOf fv :: Monoid r => (Name Expr -> r) -> Expr -> r`

lets you use some other monoid to summarize the free variables. One that I find useful all the time, for example, is `Data.Set.Lens.setOf fv :: Expr -> Data.Set.Set (Name Expr)`

(`setOf`

is in `lens`

and `Data.Set.Set`

is from `containers`

)
Super late to the convo on this one, but since I just recently got a grasp for

`fv`

and lenses more generally, this is one of the ways I frequently use `fv`

: checking whether a variable is in the free variables of another term:```
import Control.Lens (noneOf)
import Data.Typeable (Typeable)
import Unbound.Generics.LocallyNameless
-- This uses lenses because unbound-generic's fv supports lenses!
-- fv is a Getter combinator that gets the free variables of a structure, and
-- noneOf lets us fold over that structure, checking that none of them are (== t)
notInFreeVars :: (Alpha a, Typeable a) => Name a -> a -> Bool
notInFreeVars t t1 = noneOf fv (== t) t1
```

Sorry if this is a dumb question:

I have a simple lambda language and I want to do equality checking on it . I can't figure out how to unpack 2 lambda's simultaneously so they get the same De Bruijn index. or alternatively how to pick a new free var from the 2 expressions that I can apply to both.

Any thoughts?

I have a simple lambda language and I want to do equality checking on it . I can't figure out how to unpack 2 lambda's simultaneously so they get the same De Bruijn index. or alternatively how to pick a new free var from the 2 expressions that I can apply to both.

Any thoughts?

@marklemay You want

`unbind2`

or `lunbind2`

. If you have `Lam (Bind Var Expr)`

in your datatype definition, and `Lam b1`

and `Lam b2`

, you can `do`

something like this in the `Fresh m`

monad: `Just (v1, e1, _, e2) <- unbind e1 e2`

to get at the subexpressions. If you are in `LFresh m`

, then `lunbind b1 b2 $ \(Just (v1, e1, _, e2) -> ... )`

will work.
In a more general setting (for example if your have

`Lam (Bind (Var, Embed Type) Expr)`

- ie, the pattern portion of the `Bind`

is more complicated than just a single variable, you will want to hold on to both sides when you `unbind2`

. something like `Just (p1, e1, p2, e2) <- unbind b1 b2`

. And then unpack p1 and p2 - the variables will be renamed when unbinding so that they are same, but the `Embed`

ed types may differ.