Saturday, July 2, 2016

The Top 100 German Verbs (German with Jenny video)

From this helpful video from the German with Jenny YouTube channel.
  1. ich lerne / ich lernte / ich habe gelernt
  2. ich wohne / ich wohnte / ich have gewohnt
  3. ich spreche / ich sprach / ich have gesprochen
  4. ich kommen / ich kan / ich bin gekommen
  5. ich arbeite / ich arbeitete / ich have geatbeitet
  6. ich esse / ich aß / ich have gegessen
  7. ich trinke / ich trank / ich have getrunken
  8. ich habe / ich hatte / ich habe gehabt
  9. ich bin / ich war / ich bin gewessen
  10. ich verstehe / ich verstand / ich habe verstanden
  11. ich spiele / ich spielte / ich habe gespielt
  12. ich schlafe / ich schlief / ich have geschlafen
  13. ich fahre / ich fuhr / ich bin gefahren
  14. ich gehe / ich ging / ich bin gegangen
  15. ich mache / ich machte / ich habe gematch
  16. ich sage / ich sagte / ich habe gesagt
  17. ich kauge / ich kaufte / ich habe gekauft
  18. ich bezahle / ich bezahlte / ich habe behalt
  19. ich nehme / ich nahm / ich habe genommen
  20. ich mag / ich mochte
  21. ich will / ich wollte
  22. ich kann / ich konnte
  23. ich darf / ich durfte
  24. ich soll / ich sollte
  25. ich möchte / ich wollte
  26. ich weiß / ich wusste / ich habe gewusst
  27. ich kenne / ich kannte / ich habe gekannt
  28. ich denke / ich dachte / ich habe gedatch
  29. ich sehe / ich sah / ich habe gesehen
  30. ich höre / ich hörte / ich habe gehört
  31. ich gebe / ich gab / ich habe gegeben
  32. ich zeige / ich zeigte / ich habe gezeigt
  33. ich sitze / ich saß / ich habe gegessen
  34. ich liege / ich lag / ich habe gelegen
  35. ich stehe / ich stand / ich habe gestanden
  36. ich laufe / ich lief / ich bin gelaufen
  37. ich bringe / ich brachte / ich habe gebracht
  38. ich fühle / ich fühlte / ich habe gefült
  39. ich glaube / ich glaubte / ich habe geglaubt
  40. ich heiße / ich heiß
  41. ich ziehe / ich zog / ich habe gezogen
  42. ich verliere / ich verlor / ich habe verloren
  43. ich gewinne / ich gewann / ich habe gewonnen
  44. ich brauche / ich brauchte / ich habe gebraucht
  45. ich schreibe / ich schreib / ich habe geschrieben
  46. ich leibe / ich liebte / ich habe geliebt
  47. ich schwimme / ich schwamm / ich bin geschwommen
  48. ich baue / ich baute / ich habe gebaut
  49. ich schicke / ich schickte / ich habe geschickt
  50. ich lache / ich lachte / ich habe gelacht
  51. ich trage / ich trug / ich habe getragen
  52. ich werde / ich wurde / ich bin geworden
  53. ich lasse / ich ließ / ich habe gelassen
  54. ich folge / ich folgte / ich bin gefoldgt
  55. ich tue / ich tat / ich habe getan
  56. es schmeckt / es schmeckte / es hat geschmeckt
  57. es regnet / es regnete / es hat geregnet
  58. ich warte / ich wartete / ich habe gewartet
  59. ich helfe / ich half / ich habe geholfen
  60. ich lese / ich las / ich habe gelesen
  61. ich lege / ich legte / ich habe gelegt
  62. ich suche / ich suchte / ich habe gesucht
  63. ich lebe / ich lebte / ich habe gelebt
  64. ich falle / ich fiel / ich bin gefallen
  65. ich rede / ich redete / ich habe geredet
  66. ich reise / ich reiste / ich bin gereist
  67. ich fliege / ich flog / ich bin geflogen
  68. es kostet / es kostete / es hat gekostet
  69. ich singe / ich sang / ich habe gesungen
  70. ich danke / ich dankte / ich habe gedankt
  71. ich tanze / ich tanzte / ich habe getanzt
  72. ich antworte / ich antwortete / ich habe geantwortet
  73. es passiert / es passierte / es ist passiert
  74. ich probiere / ich probierte / ich habe probiert
  75. ich repariere / ich reparierte / ich habe repariert
  76. ich studiere / ich studierte / ich habe studiert
  77. ich biete an / ich bot an / ich habe angeboten
  78. ich fange an / ich fing an / ich habe angefangen
  79. ich stehe auf / ich stand auf / ich bin aufgestanden
  80. ich rufe an / ich rief an / ich habe angerufen
  81. ich mache auf / ich machte auf / ich habe aufgemacht
  82. ich sehe aus / ich sah aus / ich habe ausgesehen
  83. ich lade ein / ich lud ein / ich habe eingeladen
  84. ich steige ein / ich stieg ein / ich bin eingestiegen
  85. ich mache zu / ich machte zu / ich habe zugemacht
  86. ich bestelle / ich bestellte / ich habe bestellt
  87. ich bekomme / ich bekam / ich habe bekommen
  88. ich bestehe / ich bestand / ich habe bestanden
  89. ich besuche / ich besuchte / ich habe besucht
  90. ich entwickle / ich entwickelte / ich habe entwickelt
  91. ich erkenne / ich erkannte / ich habe erkannt
  92. ich erkläre / ich erklärte / ich habe erklärt
  93. ich erwarte / ich erwartete / ich habe erwartet
  94. ich gehöre / ich gehörte / ich habe gehört
  95. ich vergesse / ich vergaß / ich habe vergessen
  96. ich vergleiche / ich verglich / ich habe verglichen
  97. ich versuche / ich versuchte / ich habe versucht
  98. ich sehe mir an / ich sah mir an / ich habe mir angesehen
  99. ich interessiere mich / ich interessierte mich / ich habe mich interessiert
  100. ich treffe mich / ich traf mich / ich habe mich getroffen

Monday, April 25, 2016

Tuesday, May 19, 2015

representable functors

A nugget of insight about representable functors from The Catsters, episode Representables and Yoneda 3, around minute 1:00.

as it turns out, these are very very closely controlled, there's very little that they can do and they are completely controlled by very small amounts of data [...] we think that a lot is going on, when in fact we have very little choice in what's going on, and everything that's going on everywhere is just controlled by one really small bit   

Wednesday, May 13, 2015

a cabal sandbox for scripting

Later edit: this post is now obsolete, thanks to Stack.

As a way to facilitate Haskell scripting, I have created the hs-scripts repo on GitHub.

The idea is being able to run interpreted Hakell scripts, without having to install any package at the global level.

To test it, clone the repo, create a sandbox, and install the library. The repo should also be added to the PATH variable.

The library is empty at the moment, but is intended to hold common functions and definitions shared by multiple scripts.

You can invoke cabal repl in the repo to open a GHCi session with a lot of useful packages available (a poor man's Haskell Platform, if you will).

There are two batch scripts, hs.bat for Windows and for Linux. They take a Haskell script name (without extension) as parameter and execute the script in the context of the sandbox. Scripts are searched in the current directory first and then in the /scripts subfolder of the repository.

Scripts are easy to compile, if necessary.

So far there's only one script, a replica of Python's ever-useful python -m SimpleHTTPServer.

Friday, April 24, 2015

Videos for "Structure and Interpretation of Computer Programs" (1986)

  • 1A
  • 1B
  • 2A
  • 2B
  • 3A Around 1:08, the idea of program design as creating layers of languages.
  • 3B
  • 4A
  • 4B
  • 5A Interesting that they don't introduce assignment and mutability until this lecture.
  • 5B
  • 6A
  • 6B Around minute 38, a mention of Miranda, a predecessor to Haskell. Lazy evaluation as "decoupling time in the programs from time in the machine". Explanation of the disadvantages of lazy evaluation (incompatibility with side effects, "dragging tails" a.k.a. space leaks).
  • 7A Meta-circular evaluator, fixed points, Y combinator, denotational semantics.
  • 7B "There are many languages that have made a mess of themselves by adding huge numbers of features". Implementing dynamic binding and call by name.
  • 8A
  • 8B
  • 9A
  • 9B
  • 10A
  • 10B
A version of the book in .mobi format (suitable for Kindle) can be found here.

Sunday, March 29, 2015

Is ExceptT over IO really an anti-pattern ?

I was reading this exceptions best practice guide for Haskell. It contains good advice, for example about how masking all exceptions is a terrible idea. However, I sort of disagree about the "ExceptT over IO being an antipattern" part.

One of the reasons given is that "it's non-composable". I actually think that making errors explicit in the types can be more composable, especially if you want to combine or transform the errors in some  manner. Wrapping an exception to provide additional context tends to be more cumbersome than mapping over the error type with withExceptT (or first from Bifunctor).

When you compose multiple exception-throwing functions, if you aren't careful your result funcion will end up  (maybe even unbeknownst to you!) throwing a zoo of unrelated exceptions with scant context.

(Digression: the recent pipes-cliff library actually does a good job in wrapping every IOException that it encounters, tagging it with extra information.)

On the other hand, I admit that making all the errors explicit in the signature complicates it, and it becomes annoying if you consider those errors as "fatal" anyway and you don't intend to handle them, or at least not at the current layer.

Which brings us to the other main criticism: that using "ExceptT over IO" doesn't really ensure the absence of exceptions, even if it seems to imply it, and that it only provides a second, largely redundant, channel for communincating errors. In my opinion, there can be cases when we might want two separate error channels: if we want to distinguish between outright fatal vs. recoverable errors that we may want to handle, for example. Or between errors we want to annotate/map over/compose easily versus errors we just want to pass to upper layers unchanged.

In my process-streaming and conceit libraries I actually employ this dual approach. The execution functions re-throw any IO exceptions they encounter, but you can also have an explicit error type. If case the error type is never used, it remains polymorphic and we can use functions that have a simpler signature but require the error type to unify with Void.

Sunday, February 22, 2015

A dynamically generated FromJSON instance

Suppose you need to invoke a function (one like decode from pipes-aeson) that has a FromJSON constraint, but the exact parsing method required for the JSON is not fully known until runtime. Perhaps because field names in the JSON have some prefix that is only determined through reading  a configuration file, or by asking the user.

One solution is to use the tools provided by reflection package to dynamically generate the FromJSON instance at runtime, after having constructed the parse function.

The reflection repository already contains an example of a dynamically generated Monoid instance. I have adapted it for the FromJSON case; the code can be found in this gist.

Some tips for defining these kinds of local instances:

  • You never ever have to declare a Reifies instance, this is done by the internal machinery of the reflection package, through some dark magic I don't understand, even if it's explained here.
  • Instead, you use Reifies as a precondition for the instance you are actually declaring (FromJSON in this case). You are expressing something like "whenever this phantom type s reifies a typeclass dictionary at the type level, I can reflect it back and use the recovered dictionary to implement the methods of my instance".
  • The actual value passed to the reflect function is ignored, it only serves to tell the function what type reifies the value we want to reflect. Assuming you have a Reifies s a constraint, you can always pass something like Proxy :: Proxy s to reflect and obtain an a.
  • At some point, you will need a small auxiliary function to convince the compiler that the phantom type in your datatype is the same as the phantom type in the Proxy supplied by reify. Otherwise the Reifies constraint won't be satisfied, and your instance won't kick in!
  • Notice that, thanks to parametricity, the phantom type in the Proxy supplied by reify can never escape the callback. So be sure to strip from your result any newtype that still carries the phantom type!
See also this answer on Stack Overflow.