I'm still plugging away at a number of technical topics, so I wanted to share a bit more of my experience with food and weight loss.
There's a rule that I didn't mention last time, and it's possibly the most important of all of them: when you're hungry, eat something. I discovered that in order to keep losing weight over a long period, I couldn't starve myself. I had to eat whenever I felt like my body needed food and I had to eat until I wasn't hungry. Sometimes that's meant eating four or five small meals in a day.
Eating when you're hungry is a little scary when you've had problems with your weight. It's easier to have rigid rules for what and when you eat. There is, and probably always will be, a little voice that's scared of putting it all back on again. That's a reasonable concern, after all! To deal with this voice, you simply have to listen carefully to your body's signals of what it needs and trust that countless ages of evolution have - in fact - provided you with the tools you need.
Abstract Absurdities
Wednesday, January 27, 2010
Monday, January 18, 2010
Weight Loss: My Success
I've spent most of my post-teenage life struggling with my weight. About 16 months ago, I made a fairly radical change to my eating habits and I've now lost 103 lbs.
There's two major things I changed about my diet. First, I ate less sugar. Second, I ate slower. Before I get into the details, I want to clarify something. I am a vegetarian now, but that's a decision unrelated to my attempt to lose weight. I lost over 60 lbs before I became a vegetarian. Vegetarianism wasn't a prerequisite.
Eat less sugar. That sounds pretty simple, doesn't it? Unfortunately, it was a lot harder than I thought it would be. A lot of preprocessed foods, including most bread you'll find in the super market, include superfluous high-fructose corn syrup. Even foods that market themselves as healthy will include copious amounts of sugar; they just cut out the fat instead. Unfortunately, that's the opposite of what my experience has taught me. I choose fat over sugar. My body can actually break down fat and do something useful it.
I found that once I reduced the amount of sugar I consumed drastically, my appetite became more regular and manageable. I get hungry again quickly when I have sugary food and it's usually accompanied by headaches, not by an empty stomach. I also have a harder time telling just how hungry I am when I've had much sugar. It scrambles my sense of what I need. I'm really vigilant now to check the labels of food I buy in the store. I also cook more of my own meals than I used to.
Fresh fruit is my one exception to the above rule. Fruit doesn't cause me any of the problems that, say, corn syrup laden bread does. I don't entirely understand why, but it seems to be broken down differently.
Eating slow was the other key change to my life style. If I wolf down my food, I can very easily eat more than I actually need without realizing it. I discovered that if I just slow down, take breaks, and take the radical step of chewing that I can actually tell when I've had enough food. I was never aware of the whole spectrum of sensations in my stomach until I slowed down and paid attention. I was amazed to discover that there's more than just "starving" and "stuffed".
Just these two things, I think, were the most important parts of my experience losing weight.
Saturday, October 10, 2009
How to teach Category Theory?
So I'm teaching an intro to category theory course this fall at Portland State, my new place of employment.
Now, I think it's going alright. I have only 6 people in on this class, including one professor, but I imagine that if I teach it again in the future and advertise it a bit harder that there will be more.
It's been an interesting experience, though, because I've realized one of the big problems with trying to explain category theory: it's too young a field. We have all the definitions, but none of the metaphors. There's no coherent narrative to give you intuition. "Categories for the Working Mathematician", one of my all time favorite books, cheats pretty seriously on this front. It never gives a basic vocabulary to use to describe any of these structures, it just gives so many examples from other areas of math that you start to build an intuition; however, you have almost no words with which to explain this intuition.
I was inspired to write more about this because of a thread on reddit. I strongly disagree with the sentiment that one should be able to explain the concepts of category theory in terms of functional programming. Some ideas in category theory- such as representable functors, adjoints, hom-sets, topoi - are general enough that any attempts to squash them into Haskell code is simplifying to the point of confusion. An example of this is Dan Piponi's old post on the Yoneda lemma. While it's good and gives intuition, it's also a bit of a lie- the Haskell arrow (->) is not actually a hom-set and Yoneda is all about the relation between hom-sets and natural transformations that allows you to embed any category C into the category of functors from C to Set, a category with much richer logical structure. As much as the analogy to Haskell helps, I think it hurts by making the big, general, picture harder to see.
So is the solution to suck it up and just bang your head against Mac Lane, never thinking about how it relates to code? Of course not! Let's take a slight detour, first, before talking about what to do.
So Paul Graham has this famous essay - famous enough I don't even see a point to linking it - about "Blub programmers" and how they're blind to the powers of better tools because they only know Blub. It probably wasn't Graham's intent, but this essay is usually referenced by language evangelists to explain why some programmer they talk to isn't instantly willing to adopt their favorite language despite how awesome it is. It's a seductive explanation. The people who disagree with them don't "get it" or just aren't trying.
The more likely reason? They're terrible at explaining why their language is good.
When I was a grad student in physics, most of the grad students (myself included, much to my shame) joked about how dumb all the pre-med students were and how they never wanted to do any work, because that was the most convenient explanation for why there were so many complaints about how hard & confusing the labs, lectures, etc. were.
The more likely reason? We were terrible at explaining physics.
That brings me back to the course I'm teaching. I'm spending the majority of my time trying to figure out real metaphors for explaining category theory, especially with respect to its uses in Computer Science.
So far, the basic story I'm going with is that category theory is about "modeling structures". Functors are about instances of models in a target category. Natural transformations are ways to move between two models in a "coherent" fashion. I'm still fleshing out this language, and I don't know how terribly helpful it will be at the end of the day, but I'll be cleaning up and releasing my notes at the end of the term as one long pdf. The point is that there's still a lot of programmers, computer scientists, and even mathematicians that don't see category theory for the beautiful foundational math I see. Now, it's possible that they're all stupid or don't want to work.
The more likely reason?
Saturday, January 24, 2009
Fear of releasing code
Alright, so this post is going to be all Captain Emo. I wanted to write about something I've realized I do, with the hope that if someone else is unfortunate enough to have the same habit that maybe they'll realize it as well.
I sometimes have a ridiculously irrational fear of actually finishing up & releasing my personal projects.
Of course, it doesn't manifest itself as transparently as "oh, crap, people might see my code & think I punch puppies". It's much more of a "gosh, I just don't know if it's really tested enough yet" or "why don't I add a few more features first" or "I'll just tweak the API a bit" or even the insidious "I'll work on that tomorrow". Oh yes, "tomorrow" being that wonderful code word for "maybe around the time I start laying golden eggs". Sometimes I've even thrown out a good chunk of work I had finished because I thought of a "better way" which mysteriously never gets coded up.
Here's the important point I've been thinking about: something is only perfect if it doesn't exist. If you want to actually accomplish anything, you're going to release stuff that is buggy, non-optimal, & might not even compile on anyone else's machine. That's okay. It can get fixed!
I've never lost respect for someone because of a bug in a library. I've only gained respect for them when they fix it. I'm probably not the only one who feels that way.
I sometimes have a ridiculously irrational fear of actually finishing up & releasing my personal projects.
Of course, it doesn't manifest itself as transparently as "oh, crap, people might see my code & think I punch puppies". It's much more of a "gosh, I just don't know if it's really tested enough yet" or "why don't I add a few more features first" or "I'll just tweak the API a bit" or even the insidious "I'll work on that tomorrow". Oh yes, "tomorrow" being that wonderful code word for "maybe around the time I start laying golden eggs". Sometimes I've even thrown out a good chunk of work I had finished because I thought of a "better way" which mysteriously never gets coded up.
Here's the important point I've been thinking about: something is only perfect if it doesn't exist. If you want to actually accomplish anything, you're going to release stuff that is buggy, non-optimal, & might not even compile on anyone else's machine. That's okay. It can get fixed!
I've never lost respect for someone because of a bug in a library. I've only gained respect for them when they fix it. I'm probably not the only one who feels that way.
Thursday, October 30, 2008
An almost religious experience
Alright, so this is a bit off topic for this blog but I had to talk about something that amazed and astounded me.
Last night, after the Obammercial, I was flipping through the channels and I came across a sitcom called "Under One Roof" starring, not joking, Flavor Flav and a cast of people designed to make Mr. Flav not look like the craziest person on the set.
This show was so strange & surreal that at any minute I expected the real credits to roll and for it to be some extended sketch of another comedy show. For God's sake, it actually featured a wacky-Asian-stereotype cook who uttered the phrase "me so horny". The strange gesticulations, the bizarre dialog, the constant mugging & posturing for the camera all made it impossible for the brain to accept that it was watching something non-ironically meant for entertainment. Yet sure enough the credits rolled after a half-hour.
Then it hit me.
I had just witnessed the first Dadaist Sitcom. This wasn't just not funny, it was true anti-art. It wasn't that the show failed at entertaining. It succeeded at destroying the very concepts of entertainment & humor, leaving only a void. A void that challenged my fundamental assumptions about the place of entertainment in society. It made me question not why this show existed but why no other could be so profound and challenging.
Last night, after the Obammercial, I was flipping through the channels and I came across a sitcom called "Under One Roof" starring, not joking, Flavor Flav and a cast of people designed to make Mr. Flav not look like the craziest person on the set.
This show was so strange & surreal that at any minute I expected the real credits to roll and for it to be some extended sketch of another comedy show. For God's sake, it actually featured a wacky-Asian-stereotype cook who uttered the phrase "me so horny". The strange gesticulations, the bizarre dialog, the constant mugging & posturing for the camera all made it impossible for the brain to accept that it was watching something non-ironically meant for entertainment. Yet sure enough the credits rolled after a half-hour.
Then it hit me.
I had just witnessed the first Dadaist Sitcom. This wasn't just not funny, it was true anti-art. It wasn't that the show failed at entertaining. It succeeded at destroying the very concepts of entertainment & humor, leaving only a void. A void that challenged my fundamental assumptions about the place of entertainment in society. It made me question not why this show existed but why no other could be so profound and challenging.
Tuesday, October 28, 2008
Debugging & Refactoring, a mid-mortum
So I haven't touched my Bluetooth bindings in the past week, having been a bit intimidated by the prospect of sitting down and making the necessary network interfaces to actually handle doing real communication & not just simple queries. I can tell it's not going to be too hard once I get started, but it doesn't look like the most exciting thing in the world.
To get my motivation up, I worked instead on some of the small physics games into which I wanted to eventually integrate wiimote controls. Making a small game engine in Haskell hasn't been entirely easy, but that's more a function of my inexperience & that I don't think I've been using language features to their best advantage.
I lost a bit of my time wrestling with trying to make the engine interface feel "object oriented", which is where my mini-rant about type class abuse last week came from.
At this point, though, I have a good percentage of the code I need to make a few of my game ideas; however, the percentage of code that's working in all the cases it needs to is much smaller, particularly the generic collision detection & handling for polygons. There's a number of cases in my testing that keep coming up with unexpected results.
I've spent some time in the GHCi debugger, which is actually a lot more easy to use than I expected. If you haven't used the debugger yet I recommend that you read issue 10 of The Monad Reader and the rather nice tutorial provided therein. One minor thing I want to emphasize about using the debugger is that if you force a value that's returned by a function before you start stepping through the function, you won't actually step through the function by doing :step. GHCi will just continue with whatever compuation is done with the value you forced. Again, it's a minor thing but it took me a few seconds to realize why I skipped over the step-thru of one of the functions I was trying to diagnose.
Even though the debugger is actually fairly nice, my real problem is that I've made a number of small logical mistakes & built upon those mistakes without realizing I had made them in the first place. I think a good next step for this project would be to start pulling in the old QuickCheck machinery, trying to define the algebraic properties the functions in the physics engine should obey, refactoring the whole mess, and making sure it passes all of my tests from the get-go. This should prevent the "Oh, I think everything is fixed now so let's just start bouncing some squares around the screen...looks good...great...@#%*!" loop.
To get my motivation up, I worked instead on some of the small physics games into which I wanted to eventually integrate wiimote controls. Making a small game engine in Haskell hasn't been entirely easy, but that's more a function of my inexperience & that I don't think I've been using language features to their best advantage.
I lost a bit of my time wrestling with trying to make the engine interface feel "object oriented", which is where my mini-rant about type class abuse last week came from.
At this point, though, I have a good percentage of the code I need to make a few of my game ideas; however, the percentage of code that's working in all the cases it needs to is much smaller, particularly the generic collision detection & handling for polygons. There's a number of cases in my testing that keep coming up with unexpected results.
I've spent some time in the GHCi debugger, which is actually a lot more easy to use than I expected. If you haven't used the debugger yet I recommend that you read issue 10 of The Monad Reader and the rather nice tutorial provided therein. One minor thing I want to emphasize about using the debugger is that if you force a value that's returned by a function before you start stepping through the function, you won't actually step through the function by doing :step. GHCi will just continue with whatever compuation is done with the value you forced. Again, it's a minor thing but it took me a few seconds to realize why I skipped over the step-thru of one of the functions I was trying to diagnose.
Even though the debugger is actually fairly nice, my real problem is that I've made a number of small logical mistakes & built upon those mistakes without realizing I had made them in the first place. I think a good next step for this project would be to start pulling in the old QuickCheck machinery, trying to define the algebraic properties the functions in the physics engine should obey, refactoring the whole mess, and making sure it passes all of my tests from the get-go. This should prevent the "Oh, I think everything is fixed now so let's just start bouncing some squares around the screen...looks good...great...@#%*!" loop.
Labels:
bluetooth,
games,
haskell,
oh crap that was dumb
Monday, October 27, 2008
More on OS design
I've been thinking a bit again about modern type systems with respect to operating system design and I think I can describe heuristically some of my old ideas and the open questions I still have. If there are comments or ideas, I'd love to hear them.
I like modern type systems. I also like capabilities. How can we combine them together? I used to think I had more solid leads on this question, but now I feel a little shaky. What I wanted to do was have a set of capabilities, essentially just indexes into some resource mapping in the kernel, be attached to each process. The actual access rights for each resource would be encoded as a phantom type in the capability. So for each resource type you'd have some set of operations that would have preconditions about the phantom types they would find acceptable. If you wanted to pass a capability to another process you can use provided functions for making a copy securely, giving any level of permissions less than or equivalent to your own.
Now there are some things that I think make sense here: the more we can shove questions of safety into the type system, the less we have to do at runtime and the better scalability you can have. Also, I think it encourages a very different UI experience. To see a resource you need to have a capability to it, but if you're dispatching over the type of capability then presumably you could do something like have the only shell commands available for that resource be the ones that match the type signature of the resource. I'm not sure how to actually implement a feature like that, but it seems like it should be feasible on a moral level.
I feel like there's three questions I have to answer in order to take the idea from "oh that's kinda cute" to something real. The first problem is bootstrapping and snapshotting of the OS. I haven't even begun to think about this, honestly.
Another issue is how the process and system call model would have to work. We'd want the system calls to be somehow typechecked for proper capability use. Again, I'm not sure of a good scheme for this that doesn't restrict execution to just the host language. Perhaps the bullet that has to be bitten involves making some form of FFI for each compiler that should target this system so that the system calls are made in the host language and then type checked at compilation.
The last issue that's still fuzzy in my head involves storing capabilities for a process. Now, it's all fine and dandy to say 'it's a set', but most data structures in a language such as Haskell are homogenous. What I need is a heterogenous container that doesn't completly lose type information, which means that using type classes and existentials is right out. I know Oleg Kiselyov has done work with thing like HList, but that's something I don't know much about.
I like modern type systems. I also like capabilities. How can we combine them together? I used to think I had more solid leads on this question, but now I feel a little shaky. What I wanted to do was have a set of capabilities, essentially just indexes into some resource mapping in the kernel, be attached to each process. The actual access rights for each resource would be encoded as a phantom type in the capability. So for each resource type you'd have some set of operations that would have preconditions about the phantom types they would find acceptable. If you wanted to pass a capability to another process you can use provided functions for making a copy securely, giving any level of permissions less than or equivalent to your own.
Now there are some things that I think make sense here: the more we can shove questions of safety into the type system, the less we have to do at runtime and the better scalability you can have. Also, I think it encourages a very different UI experience. To see a resource you need to have a capability to it, but if you're dispatching over the type of capability then presumably you could do something like have the only shell commands available for that resource be the ones that match the type signature of the resource. I'm not sure how to actually implement a feature like that, but it seems like it should be feasible on a moral level.
I feel like there's three questions I have to answer in order to take the idea from "oh that's kinda cute" to something real. The first problem is bootstrapping and snapshotting of the OS. I haven't even begun to think about this, honestly.
Another issue is how the process and system call model would have to work. We'd want the system calls to be somehow typechecked for proper capability use. Again, I'm not sure of a good scheme for this that doesn't restrict execution to just the host language. Perhaps the bullet that has to be bitten involves making some form of FFI for each compiler that should target this system so that the system calls are made in the host language and then type checked at compilation.
The last issue that's still fuzzy in my head involves storing capabilities for a process. Now, it's all fine and dandy to say 'it's a set', but most data structures in a language such as Haskell are homogenous. What I need is a heterogenous container that doesn't completly lose type information, which means that using type classes and existentials is right out. I know Oleg Kiselyov has done work with thing like HList, but that's something I don't know much about.
Subscribe to:
Posts (Atom)