2 kyu
What happened to good old if-statements?
30mrum
Loading description...
Functional Programming
View
This comment has been reported as {{ abuseKindText }}.
Show
This comment has been hidden. You can view it now .
This comment can not be viewed.
- |
- Reply
- Edit
- View Solution
- Expand 1 Reply Expand {{ comments?.length }} replies
- Collapse
- Spoiler
- Remove
- Remove comment & replies
- Report
{{ fetchSolutionsError }}
-
-
Your rendered github-flavored markdown will appear here.
-
Label this discussion...
-
No Label
Keep the comment unlabeled if none of the below applies.
-
Issue
Use the issue label when reporting problems with the kata.
Be sure to explain the problem clearly and include the steps to reproduce. -
Suggestion
Use the suggestion label if you have feedback on how this kata can be improved.
-
Question
Use the question label if you have questions and/or need help solving the kata.
Don't forget to mention the language you're using, and mark as having spoiler if you include your solution.
-
No Label
- Cancel
Commenting is not allowed on this discussion
You cannot view this solution
There is no solution to show
Please sign in or sign up to leave a comment.
My solution passes sample tests, but fails to compile on submission
Idk, it looks like an internal problem
Seems like the original solution was automaticly ported to a new GHC version, and that broke it. The code compiles fine with
NoPolyKinds
language extension set, so i propose enabling itThanks for the suggestion. I have added
NoPolyKinds
to the initial solution. I didn't need it in my solution, but haven't investigated where exactly the issue comes from, yet.In case anyone is interested in creating another follow-up imperative kata, it would be cool to require correct early returns:
Just an observation: default signatures like
return an
Imperative … s s …
, which allows putting these statements betweenif'
,elif'
andelse'
:I'd prefer if this was illegal and the types of non-branching statements were restricted to
Imperative … s NothingYet …
, given the kata's focus on type correctness.But sure, this can be seen as an intentional language feature. And things will probably stay the same to avoid extra work, breaking existing solutions, etc. You may even add tests that cover this feature.
Submission tests expect
HasValue
,Imperative
andVar
to be exported. Consider adding these to the export list in the initial solution templateThe initial solution exports everything, so that isn't a problem, is it?
Hmmm, you're right. Apparently, I didn't check the initial solution before posting this. I've encountered that error because I added an export list (probably copied it from sample tests' imports). Export lists play nicely with IDEs. For instance, they allow me to "rename symbol" in VSCode. I suggest adding one
The meaning of the
(.=)
operation should be clarified (in the initial code comments). It took me some time to realized that it is an assignment operation.Also, I suggest to clarify that
toString
is supposed to work with variables only (otherwise it is necessary to use another GHC extension to type check it).Thanks for the feedback! I added these clarifications to the initial code for
.=
andtoString
.(+=)
,(-=)
,(*=)
,push
andtoString
are not given type definition, which is understandable. However, the tests do not use the most general types for these (Num a
,[a]
andShow a
) because onlyInteger
andString
are used in the tests. I don't think this is desirable.Good point. I made sure that each of these operations works with at least two different types (like Int and Float). That should be enough right?
To make my life easier when testing I also added the (.=) function to implement. With that we also can have a nice
isEven
program, which I added aswell.Last change is to the export/import list. Now everything is exported/imported by default, so that I don't have to touch these anymore if I decide to change an export again.
(These changes invalidated your solution)
If you choose to import everything in user solution, it should also be
qualified
so things defined in user solution will not collide with things defined in the tests.Ah yes you are right. I changed the imports to back to being explicit.
;-)
The initial code is kinda getting a bit too funky there (like
RebindableSyntax
,data TODO
reused everywhere, andmodule Skeleton
). I think at least the module name should be the actual one, akamodule Imperative
.Also, do we need to have so many unexported/untested functions and some strangely missing type definitions like
def
(which you can get by letting the sample tests typecheck anyway)? The former should probably be mentioned, and the latter is kinda unnecessary.The
module Skeleton
was a mistake on my part. I replaced it with the correctmodule Imperative
.I removed the unexported functions from the initial solution, I didn't have a good reason to include them. I also added the missing type definition for
def
.Lasty, probably the biggest change, I removed the TODO types. while/if/else are now fully typed. That means that the typeclass I used also appears in the initial solution.
The
Imperative
type is still hidden, because I think it's interesting to figure out how to implement it.Does it look better now? I am a bit worried that the variable/value typeclass thing is a bit too much at once.
Oh and with the removal of the TODO types the initial solution now compiles, which I think is great.
Is the new type definition for
Imperative
correct? It used to be anewtype
, now it'sdata
.I used
data
so that I can define the left-hand side of the type while leaving the right-hand side out.newtype
won't let me do that, but for the solution eithernewtype
ordata
is fine.;-)
I can't even solve your Kata, so I may be way off base here.
Your
if'
andelif'
look like they take 3 arguments, instead of a singleBool
( which could be expressed between parentheses, JS-style ). Wouldn't passing aBool
be more flexible for conditions, without materially affecting the kata?Thanks for the feedback!
I use the more complicated signature to make it possible to compare both variables and values using built-in functions like (<). With Bool we wouldn't be able to compare the mutable variables we create. For example:
Does this make sense? If so I would add a hint for that.
It looks like this kata tried a different approach in the past, where
Var
s were instances ofNum
, but ended up with a version that's similar to what I am using here.It makes sense. Could
if'
and friends take a monadic boolean instead of a pure one? You'd have to lift the built-in comparator and the value into the monad, of course, but that can be done polymorphically, so painlessly.Thing is, with the current design,
a > 3 && a < 10
is never going to work, and a ( monadic or pure ) boolean would offer that flexibility. It's not the essence of the kata, but it would seem very nice to have. :]I can image this being done by redefining the operators (for example
(<) = someLiftFunction P.(<)
), which I would like to avoid. How can it be done more painlessly?Maybe my approach is already more complicated than it needs to be. For example
while someVar (< 0)
is a bit simpler because it only accepts aVar
on the left side.The meat of the kata should be defining mutable variabes and the if/else control flow, while keeping some kind of clean python-like syntax.
Let me know if you feel like there is anything else in the kata that makes it more convoluted than necessary.
It would look something like
while (liftM2 (<) a (pure 3))
orwhile ((<) <$> a <*> pure 3)
, which of course looks nothing like Python. If you want to avoidsomeLiftFunction (<)
, the necessary intelligence will have to be built in towhile
, which is not the most modular or flexible design, but looks most like Python.