<div dir="auto">Thanks so much! You just taught me many things I didn't know!<div dir="auto"><br></div><div dir="auto">The code is working by the way. :)</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Dec 31, 2016 3:59 AM, "Li-yao Xia" <<a href="mailto:li-yao.xia@ens.fr">li-yao.xia@ens.fr</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Cody,<br>
<br>
I forgot to keep Haskell-cafe in copy.<br>
<br>
> Are you saying that my forall applies to both a and b, but not only a? And<br>
> that a is what (Lens (Record rs) Chicago -> (...)) expands to?<br>
<br>
That sounds about right.<br>
<br>
Try this:<br>
<br>
dateBetween :: (forall f. Functor f => (Chicago -> f Chicago) -> Record rs -> f (Record rs))<br>
-> Day<br>
-> Day<br>
-> Pipe (Record rs) (Record rs) IO m<br>
<br>
Or, a bit refactored:<br>
<br>
type Lens s a = forall f. Functor f => (a -> f a) -> (s -> f s)<br>
<br>
dateBetween :: Lens (Record rs) Chicago<br>
-> Day -> Day -> Pipe (Record rs) (Record rs) IO m<br>
<br>
> Where does f1 come from? Does GHC just come up with it because my type<br>
> variable doesn't satisfy it?<br>
<br>
When you write this<br>
<br>
dateBetween :: forall (rs :: [*]) (m :: *) (f :: * -> *).<br>
(Functor f) =><br>
((Chicago -> f Chicago) -> Record rs -> f (Record rs))<br>
-> Day<br>
-> Day<br>
-> Pipe (Record rs) (Record rs) IO m<br>
dateBetween target start end = ...<br>
<br>
The parameter target is a monomorphic function, with f instantiated at the call site of dateBetween. This means that dateBetween can not assume anything about f apart from the fact that it is an instance of Functor, i.e., f must be abstract.<br>
<br>
Then we have:<br>
<br>
let targetDate = rget target r<br>
<br>
but this is the type of rget:<br>
<br>
rget :: (forall f . Functor f => (a -> f a) -> Record rs -> f (Record rs)) -> Record rs -> a<br>
<br>
rget expects a polymorphic function, while target is monomorphic. The compiler tries to unify "f" from the type signature of dateBetween, and "f" from the type signature of rget. To avoid confusion, the compiler does renaming, so that different variables (identified by where they are bound) have different names, and that's where "f1" comes from:<br>
<br>
rget :: forall a1 rs1. (forall f1 . Functor f1 => (a1 -> f1 a1) -> Record rs1 -> f1 (Record rs1)) -> Record rs1 -> a1<br>
<br>
Applying rget to (target :: (Chicago -> f Chicago) -> Record rs -> f (Record rs)), the compiler tries to unify f and f1, and fails because they are "rigid", meaning, they can't be instantiated. f is rigid because it is abstract in the body of dateBetween, f1 is rigid because it is the type parameter of the polymorphic function rget expects.<br>
<br>
Li-yao<br>
<br>
On 12/31/2016 09:07 AM, Cody Goodman wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Li-yao,<br>
<br>
Are you saying that my forall applies to both a and b, but not only a? And<br>
that a is what (Lens (Record rs) Chicago -> (...)) expands to?<br>
<br>
In either case, I don't understand what action I can take based on what was<br>
you said and what I understand from it :/<br>
<br>
Where does f1 come from? Does GHC just come up with it because my type<br>
variable doesn't satisfy it?<br>
<br>
Thanks,<br>
<br>
Cody<br>
<br>
On Sat, Dec 31, 2016 at 2:54 AM, Li-yao Xia <<a href="mailto:li-yao.xia@ens.fr" target="_blank">li-yao.xia@ens.fr</a>> wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Cody,<br>
<br>
You wrote something of the shape<br>
<br>
forall f. Functor f => a -> b<br>
<br>
which means<br>
<br>
forall f. Functor f => (a -> b)<br>
<br>
but not<br>
<br>
(forall f. Functor f => a) -> b<br>
<br>
which would be what (Lens (Record rs) Chicago -> (...)) expands to.<br>
<br>
Regards,<br>
Li-yao<br>
<br>
<br>
On 12/31/2016 08:45 AM, Cody Goodman wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Thanks for the help Li-yao, but I still have a type error after using Rank<br>
N Types. I have updated my code on github<br>
<a href="https://github.com/codygman/frames-credit-card-trans-demo/bl" rel="noreferrer" target="_blank">https://github.com/codygman/fr<wbr>ames-credit-card-trans-demo/bl</a><br>
ob/master/src/Main.hs#L45()<br>
and pasted below:<br>
<br>
dateBetween :: forall (rs :: [*]) (m :: *) (f :: * -> *).<br>
(Functor f) =><br>
((Chicago -> f Chicago) -> Record rs -> f (Record rs))<br>
-> Day<br>
-> Day<br>
-> Pipe (Record rs) (Record rs) IO m<br>
dateBetween target start end = P.filter go<br>
where go :: Record rs -> _<br>
go r = let targetDate = (rget target r) :: Chicago<br>
targetDate' = chicagoToZoned targetDate :: ZonedTime<br>
targetDay = localDay (zonedTimeToLocalTime targetDate')<br>
:: Day<br>
in<br>
targetDay >= start && targetDay < end<br>
-- type error<br>
-- src/Main.hs:53:39: error: …<br>
-- • Couldn't match type ‘f’ with ‘f1’<br>
-- ‘f’ is a rigid type variable bound by<br>
-- the type signature for:<br>
-- dateBetween :: forall (rs :: [*]) m (f :: * -> *).<br>
-- Functor f =><br>
-- ((Chicago -> f Chicago) -> Record rs -> f<br>
(Record rs))<br>
-- -> Day -> Day -> Pipe (Record rs) (Record rs)<br>
IO m<br>
-- at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>45:45<br>
-- ‘f1’ is a rigid type variable bound by<br>
-- a type expected by the context:<br>
-- forall (f1 :: * -> *).<br>
-- Functor f1 =><br>
-- (Chicago -> f1 Chicago) -> Record rs -> f1 (Record rs)<br>
-- at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>53:34<br>
-- Expected type: (Chicago -> f1 Chicago)<br>
-- -> Record rs -> f1 (Record rs)<br>
-- Actual type: (Chicago -> f Chicago) -> Record rs -> f (Record<br>
rs)<br>
-- • In the first argument of ‘rget’, namely ‘target’<br>
-- In the expression: (rget target r) :: Chicago<br>
-- In an equation for ‘targetDate’:<br>
-- targetDate = (rget target r) :: Chicago<br>
-- • Relevant bindings include<br>
-- target :: (Chicago -> f Chicago) -> Record rs -> f (Record rs)<br>
-- (bound at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>51:13)<br>
-- dateBetween :: ((Chicago -> f Chicago)<br>
-- -> Record rs -> f (Record rs))<br>
-- -> Day -> Day -> Pipe (Record rs) (Record rs)<br>
IO m<br>
-- (bound at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>51:1)<br>
-- Compilation failed.<br>
<br>
On Sat, Dec 31, 2016 at 2:21 AM, Li-yao Xia <<a href="mailto:li-yao.xia@ens.fr" target="_blank">li-yao.xia@ens.fr</a>> wrote:<br>
<br>
Hello Cody,<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Complete the type annotation, using RankNTypes<br>
<br>
dateBetween :: Lens Record Chicago -> ...<br>
<br>
GHC does not infer higher-rank types, because it is an undecidable<br>
problem<br>
in general, so you must annotate polymorphic parameters explicitly.<br>
<br>
Regards,<br>
Li-yao<br>
<br>
<br>
On 12/31/2016 07:56 AM, Cody Goodman wrote:<br>
<br>
I have the following code and error(also seen at<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<a href="https://github.com/codygman/frames-credit-card-trans-demo/bl" rel="noreferrer" target="_blank">https://github.com/codygman/fr<wbr>ames-credit-card-trans-demo/bl</a><br>
ob/master/src/Main.hs#L28<br>
):<br>
<br>
<br>
-- between meaning on or after start but before end<br>
dateBetween :: _<br>
-> Day<br>
-> Day<br>
-> Pipe (Record rs) (Record rs) IO r<br>
dateBetween target start end = P.filter go<br>
where go :: Record rs -> _<br>
go r = let targetDate = rget target r :: Chicago<br>
targetDate' = chicagoToZoned targetDate :: ZonedTime<br>
targetDay = localDay (zonedTimeToLocalTime<br>
targetDate')<br>
:: Day<br>
in<br>
targetDay >= start && targetDay < end<br>
-- type error<br>
-- src/Main.hs:48:38: error: …<br>
-- • Couldn't match expected type ‘(Chicago -> f Chicago)<br>
-- -> Record rs1 -> f (Record rs1)’<br>
-- with actual type ‘t’<br>
-- because type variable ‘f’ would escape its scope<br>
-- This (rigid, skolem) type variable is bound by<br>
-- a type expected by the context:<br>
-- Functor f => (Chicago -> f Chicago) -> Record rs1 -> f<br>
(Record<br>
rs1)<br>
-- at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>48:33-45<br>
-- • In the first argument of ‘rget’, namely ‘target’<br>
-- In the expression: rget target r :: Chicago<br>
-- In an equation for ‘targetDate’:<br>
-- targetDate = rget target r :: Chicago<br>
-- • Relevant bindings include<br>
-- r :: Record rs1<br>
-- (bound at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>48:12)<br>
-- go :: Record rs1 -> Bool<br>
-- (bound at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>48:9)<br>
-- target :: t<br>
-- (bound at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>46:13)<br>
-- dateBetween :: t -> Day -> Day -> Pipe (Record rs) (Record<br>
rs)<br>
IO r<br>
-- (bound at<br>
/home/cody/source/frames-credi<wbr>t-card-trans-demo/src/Main.hs:<wbr>46:1)<br>
-- Compilation failed.<br>
<br>
Perhaps it's late, but I'm fairly sure I've done something like this<br>
before.<br>
<br>
Thanks,<br>
<br>
Cody<br>
<br>
<br>
<br>
______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bi<wbr>n/mailman/listinfo/haskell-caf<wbr>e</a><br>
Only members subscribed via the mailman list are allowed to post.<br>
<br>
<br>
<br>
</blockquote></blockquote>
<br>
</blockquote></blockquote>
<br>
</blockquote>
</blockquote></div></div>