Wvv | 16 Oct 23:06 2013
Picon

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
  :: (Monad (t1 (t2 m)), Monad (t2 m), Monad m, MonadTrans t,
      MonadTrans t1, MonadTrans t2) =>
     m a -> t (t1 (t2 m)) a

My best solution looks like:

data MT = M | T Int MT
liftN :: forall tm. ( forall x n.
		   Monad 'M, Monad (x :: MT),
		   MonadTrans ('T n),  
         ) => Int -> 'M a ->  ('T 0) (tm :: MT) a
liftN n
(Continue reading)

Dan Burton | 16 Oct 23:32 2013
Picon

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 <vitea3v <at> rambler.ru> 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
  :: (Monad (t1 (t2 m)), Monad (t2 m), Monad m, MonadTrans t,
      MonadTrans t1, MonadTrans t2) =>
     m a -> t (t1 (t2 m)) a

My best solution looks like:

data MT = M | T Int MT
liftN :: forall tm. ( forall x n.
                   Monad 'M, Monad (x :: MT),
                   MonadTrans ('T 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
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
adam vogt | 17 Oct 01:25 2013
Picon

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

--
Adam
Wvv | 17 Oct 21:19 2013
Picon

Re: liftN

Nice! Thanks!

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

Adam Vogt wrote
> 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
> 
> --
> Adam
> _______________________________________________
> Haskell-Cafe mailing list

> Haskell-Cafe <at> 

> http://www.haskell.org/mailman/listinfo/haskell-cafe

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738652.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
adam vogt | 18 Oct 00:09 2013
Picon

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
http://hackage.haskell.org/package/layers-0.1/docs/Control-Monad-Layer.html#t:lift

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.

--
Adam
Wvv | 19 Oct 00:07 2013
Picon

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
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
wren ng thornton | 17 Oct 00:22 2013

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://community.haskell.org/~wren/wren-extras/dist/doc/html/wren-extras/Data-List-ZipWithN.html>
* <http://okmij.org/ftp/Haskell/polyvariadic.html#polyvartype-fn>
* <http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html>
* <http://hackage.haskell.org/package/TypeCompose-0.9.9/docs/Data-Zip.html>

--

-- 
Live well,
~wren
Stephen Tetley | 17 Oct 19:06 2013
Picon

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://community.haskell.org/~wren/wren-extras/dist/doc/html/wren-extras/Data-List-ZipWithN.html>
> * <http://okmij.org/ftp/Haskell/polyvariadic.html#polyvartype-fn>
> * <http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html>
> * <http://hackage.haskell.org/package/TypeCompose-0.9.9/docs/Data-Zip.html>
>
> --
> Live well,
> ~wren
>
Wvv | 17 Oct 19:44 2013
Picon

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://community.haskell.org/~wren/wren-extras/dist/doc/html/wren-extras/Data-List-ZipWithN.html&gt;
> * &lt;http://okmij.org/ftp/Haskell/polyvariadic.html#polyvartype-fn&gt;
> * &lt;http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html&gt;
> *
> &lt;http://hackage.haskell.org/package/TypeCompose-0.9.9/docs/Data-Zip.html&gt;
> 
> -- 
> Live well,
> ~wren
> _______________________________________________
> Haskell-Cafe mailing list

> Haskell-Cafe <at> 

> http://www.haskell.org/mailman/listinfo/haskell-cafe

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738648.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
Arjun Comar | 17 Oct 20:05 2013
Picon

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 <vitea3v <at> rambler.ru> 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://community.haskell.org/~wren/wren-extras/dist/doc/html/wren-extras/Data-List-ZipWithN.html&gt;
> * &lt;http://okmij.org/ftp/Haskell/polyvariadic.html#polyvartype-fn&gt;
> * &lt;http://paczesiowa.blogspot.com/2010/03/generalized-zipwithn.html&gt;
> *
> &lt;http://hackage.haskell.org/package/TypeCompose-0.9.9/docs/Data-Zip.html&gt;
>
> --
> Live well,
> ~wren
> _______________________________________________
> Haskell-Cafe mailing list

> Haskell-Cafe <at>

> http://www.haskell.org/mailman/listinfo/haskell-cafe





--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738648.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Wvv | 19 Oct 00:10 2013
Picon

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
> monad-layers&lt;http://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Overview.html&gt;package
> that obviates the need for a function like liftN.
> 
> Thanks,
> Arjun
> 
> 
> _______________________________________________
> Haskell-Cafe mailing list

> Haskell-Cafe <at> 

> http://www.haskell.org/mailman/listinfo/haskell-cafe

--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738719.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
Edward Kmett | 30 Oct 20:11 2013
Picon

Re: liftN

I find that highly unlikely. =P

-Edward


On Fri, Oct 18, 2013 at 6:10 PM, Wvv <vitea3v <at> rambler.ru> wrote:
It looks like monad-transfomers become deprecated soon :))))


Arjun Comar wrote
> This is slightly off-topic, but you might be interested in the
> monad-layers&lt;http://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Overview.html&gt;package
> that obviates the need for a function like liftN.
>
> Thanks,
> Arjun
>
>
> _______________________________________________
> Haskell-Cafe mailing list

> Haskell-Cafe <at>

> http://www.haskell.org/mailman/listinfo/haskell-cafe





--
View this message in context: http://haskell.1045720.n5.nabble.com/liftN-tp5738612p5738719.html
Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Gmane