
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.

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
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@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Wed, Oct 16, 2013 at 5:32 PM, Dan Burton
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

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

On Thu, Oct 17, 2013 at 3:19 PM, Wvv
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#... 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

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.

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/Dat... * 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

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
You should check out the solutions for encoding polyvariadic functions, e.g.
* http://community.haskell.org/~wren/wren-extras/dist/doc/html/wren-extras/Dat... * 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

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.
* <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 _______________________________________________ Haskell-Cafe mailing list
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.

This is slightly off-topic, but you might be interested in the
monad-layershttp://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Over...package
that obviates the need for a function like liftN.
Thanks,
Arjun
On Thu, Oct 17, 2013 at 1:44 PM, Wvv
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.
* < 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 _______________________________________________ Haskell-Cafe mailing list
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@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

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

I find that highly unlikely. =P
-Edward
On Fri, Oct 18, 2013 at 6:10 PM, Wvv
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< http://hackage.haskell.org/package/layers-0.1/docs/Documentation-Layers-Overview.html>package that obviates the need for a function like liftN.
Thanks, Arjun
_______________________________________________ Haskell-Cafe mailing list
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@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (7)
-
adam vogt
-
Arjun Comar
-
Dan Burton
-
Edward Kmett
-
Stephen Tetley
-
wren ng thornton
-
Wvv