16 Oct 2013 23:06

## liftN

```I try to write a function "liftN", but I'm not satisfied with result.

lift :: (MonadTrans t) => Monad m => m a -> t m a

liftN n
| n < 1       = error "liftN: n<1"
| n == 1     = lift
| otherwise = lift . (liftN (n-1))

1) I know(?), that it is impossible to write liftN now: typechecker can't
decide which signature it is.
2) Main reason is finite recursive constraint

3) Let's think, it is possible to write
Main candidates: promoted data and data-kinds

For example,
lift . lift . lift
m a -> t (t1 (t2 m)) a

My best solution looks like:

data MT = M | T Int MT
liftN :: forall tm. ( forall x n.
) => Int -> 'M a ->  ('T 0) (tm :: MT) a
liftN n
```

16 Oct 2013 23:32

### Re: liftN

My "solution" is a lot less interesting

lift1 = lift
lift2 = lift . lift1
lift3 = lift . lift2
lift4 = lift . lift3
lift5 = lift . lift4

What you want seemingly requires dependent types, because the result type depends on the Int that you pass in. Haskell is not well equipped to handle this, though you could probably whip up some Template Haskell to get the job done for cases where the Int can be determined at compile time.

-- Dan Burton

On Wed, Oct 16, 2013 at 2:06 PM, Wvv wrote:
I try to write a function "liftN", but I'm not satisfied with result.

lift :: (MonadTrans t) => Monad m => m a -> t m a

liftN n
| n < 1       = error "liftN: n<1"
| n == 1     = lift
| otherwise = lift . (liftN (n-1))

1) I know(?), that it is impossible to write liftN now: typechecker can't
decide which signature it is.
2) Main reason is finite recursive constraint

3) Let's think, it is possible to write
Main candidates: promoted data and data-kinds

For example,
lift . lift . lift
m a -> t (t1 (t2 m)) a

My best solution looks like:

data MT = M | T Int MT
liftN :: forall tm. ( forall x n.
) => Int -> 'M a ->  ('T 0) (tm :: MT) a
liftN n
| n < 1     = error "liftN:  n < 1"
| n == 1    = lift
| otherwise = lift . (liftN (n-1))

Am I miss something?
I think this function could look much prettier.
But I don't know how.

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612.html
_______________________________________________

```_______________________________________________
```
17 Oct 2013 01:25

### Re: liftN

```On Wed, Oct 16, 2013 at 5:32 PM, Dan Burton <danburton.email <at> gmail.com> wrote:
> My "solution" is a lot less interesting
>
> lift1 = lift
> lift2 = lift . lift1
> lift3 = lift . lift2
> lift4 = lift . lift3
> lift5 = lift . lift4

Hi,

The number of lifts can be decided if you have a class, and use it in
such a way that the argument and result types are known. It's more
involved to add a type-level Nat that keeps count. Both options are
done here: https://gist.github.com/aavogt/7016708

--
```
17 Oct 2013 21:19

### Re: liftN

```Nice! Thanks!

As I understand, your solution it is not liftN, but another nice function:
liftUp (it lifts up to Monad).

> Hi,
>
> The number of lifts can be decided if you have a class, and use it in
> such a way that the argument and result types are known. It's more
> involved to add a type-level Nat that keeps count. Both options are
> done here: https://gist.github.com/aavogt/7016708
>
> --
> _______________________________________________

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738652.html
```
18 Oct 2013 00:09

### Re: liftN

```On Thu, Oct 17, 2013 at 3:19 PM, Wvv <vitea3v <at> rambler.ru> wrote:
> Nice! Thanks!
>
> As I understand, your solution it is not liftN, but another nice function:
> liftUp (it lifts up to Monad).

The simpler liftN I wrote seems to be the same as

In the LiftN_ module, the expression (liftN (Proxy :: Proxy 3)) has
the same type as the example (lift . lift . lift) you gave, and the
recursion in the class instance look pretty much repeats the lift .
(liftN (n-1)) you wrote.

On the other hand, I'm not sure what you're expecting from the type
signature you wrote for liftN. Promoted types don't have values, which
is why things like f :: True and  g :: 'False -> () are kind errors.

--
```
19 Oct 2013 00:07

### Re: liftN

```> n the LiftN_ module, the expression (liftN (Proxy :: Proxy 3)) has the same
type as the example (lift . lift . lift) you gave

Oh, I don't check this module yet, I have GHC 7.6.3 only.
It looks like I misunderstood the code, I'm sorry.

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738718.html
```
17 Oct 2013 00:22

### Re: liftN

```On 10/16/13 5:06 PM, Wvv wrote:
> I try to write a function "liftN", but I'm not satisfied with result.
>
> lift :: (MonadTrans t) => Monad m => m a -> t m a
>
> liftN n
>      | n < 1       = error "liftN: n<1"
>      | n == 1     = lift
>      | otherwise = lift . (liftN (n-1))
>
> 1) I know(?), that it is impossible to write liftN now: typechecker can't
> decide which signature it is.

You should check out the solutions for encoding polyvariadic functions, e.g.

*
* <http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html>

--

--
Live well,
~wren
```
17 Oct 2013 19:06

### Re: liftN

```See also 'An n-ary zipWith in Haskell' - Daniel Fridlender and Mia Indrika

http://www.brics.dk/RS/98/38/

On 16 October 2013 23:22, wren ng thornton <wren <at> freegeek.org> wrote:

> You should check out the solutions for encoding polyvariadic functions, e.g.
>
> *
> * <http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html>
>
> --
> Live well,
> ~wren
>
```
17 Oct 2013 19:44

### Re: liftN

```Thank you!

Unfortunately, liftN always take same number of arguments.
So, polyvariadic "magic" don't work here.

wren ng thornton wrote
> On 10/16/13 5:06 PM, Wvv wrote:
>> I try to write a function "liftN", but I'm not satisfied with result.
>>
>> lift :: (MonadTrans t) => Monad m => m a -> t m a
>>
>> liftN n
>>      | n < 1       = error "liftN: n<1"
>>      | n == 1     = lift
>>      | otherwise = lift . (liftN (n-1))
>>
>> 1) I know(?), that it is impossible to write liftN now: typechecker can't
>> decide which signature it is.
>
> You should check out the solutions for encoding polyvariadic functions,
> e.g.
>
> *
> * &lt;http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html&gt;
> *
>
> --
> Live well,
> ~wren
> _______________________________________________

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738648.html
```
17 Oct 2013 20:05

### Re: liftN

This is slightly off-topic, but you might be interested in the monad-layers package that obviates the need for a function like liftN.

Thanks,
Arjun

On Thu, Oct 17, 2013 at 1:44 PM, Wvv wrote:
Thank you!

Unfortunately, liftN always take same number of arguments.
So, polyvariadic "magic" don't work here.

wren ng thornton wrote
> On 10/16/13 5:06 PM, Wvv wrote:
>> I try to write a function "liftN", but I'm not satisfied with result.
>>
>> lift :: (MonadTrans t) => Monad m => m a -> t m a
>>
>> liftN n
>>      | n < 1       = error "liftN: n<1"
>>      | n == 1     = lift
>>      | otherwise = lift . (liftN (n-1))
>>
>> 1) I know(?), that it is impossible to write liftN now: typechecker can't
>> decide which signature it is.
>
> You should check out the solutions for encoding polyvariadic functions,
> e.g.
>
> *
> * &lt;http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html&gt;
> *
>
> --
> Live well,
> ~wren
> _______________________________________________

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738648.html
_______________________________________________

```_______________________________________________
```
19 Oct 2013 00:10

### Re: liftN

```It looks like monad-transfomers become deprecated soon :))))

Arjun Comar wrote
> This is slightly off-topic, but you might be interested in the
> that obviates the need for a function like liftN.
>
> Thanks,
> Arjun
>
>
> _______________________________________________

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738719.html
```
30 Oct 2013 20:11

### Re: liftN

I find that highly unlikely. =P

-Edward

On Fri, Oct 18, 2013 at 6:10 PM, Wvv wrote:
It looks like monad-transfomers become deprecated soon :))))

Arjun Comar wrote
> This is slightly off-topic, but you might be interested in the
> that obviates the need for a function like liftN.
>
> Thanks,
> Arjun
>
>
> _______________________________________________

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738719.html
_______________________________________________

```_______________________________________________