## Haskell in Q

My new job will involve coding in Q. Q is a scripting language derived from APL. It is mostly used for stuff related to trading and finance. I don’t know it yet, I’m supposed to learn it on the job, so I decided to have a look at it.
As an exercise, I took a couple of Haskell functions in the standard Data.List module and tried to see how one can express them in Q. Experienced Q developers (called “Q gods” in the Q terminology) will probably laugh at my code, but well, I have to start from something. Any corrections and idioms from Q gods are welcome.

Here are a couple of trivial functions that are special cases of builtin Q functions

```init: {-1_x}

tail: {1_x}

Q is a functional language. It allows to take functions as parameters in functions. Here the `takeWhile` function takes a predicate as its first parameter. The code is probably too imperative for Q, I am sure there is a better way.

```takeWhile:{[p;xs]
i:0;
while[(i < count xs) & p[xs[i]]; i+:1];
xs[til i] / quite readable, isn't it
}```

Q supports anonymous functions so one can call `takeWhile` as follows:

```q) takeWhile [{x>0}; (1;2;4;0;3;4;5)]
1 2 4```

Here ` {x>0}` is an anonymous function that returns true (1b) when the argument is positive and 0b when it is less or equal 0.

My first shot at Haskell’s `intersperse` looked like this:

`intersperse: { -1 _ raze y ,' x }`

Here `y ,' x` creates pairs with first element taken from y and second equal to x:

```(1;2;3) ,' 0
1 0
2 0
3 0```

`raze` removes one level of nesting so we get a list instead of a list of pairs:

```raze (1;2;3) ,' 0
1 0 2 0 3 0```

`-1 _` then drops the last element

This works well, but only when the first argument is an atom (not list).

```intersperse[0;(1;2;3)]
1 0 2 0 3```

But when we want to intersperse a list we get an error:

```q) intersperse [(0;0);((1;1);(2;2);(3;3))]
{-1 _ raze y ,' x }
'length```

To get a more general version we first define Haskell’s replicate:

```replicate: {[n;e]
a: {x, (enlist z)};
() a[ ; ;e]/ (til n) / folds the dyadic (binary) function a[ ; ;e] over a list of length n
}```

Here `a: {x, (enlist z)}` creates a triadic (ternary) function that appends the third argument to the first and ignores the second.
This replicate implementation seems too complicated for such simple task, but I was unable to figure out anything simpler.

We also need Haskell’s `zip`:

`zip: { x {(x;y)}' y }`

And now we can define intersperse:

`intersperse: { -1 _ raze zip [y ; replicate[count y;x]] }`

This works better than the first attempt:

```q) intersperse [(0;0);((1;1);(2;2);(3;3))]
1 1
0 0
2 2
0 0
3 3```

Haskell’s `map` is kind of redundant in Q as unary functions (called “monadic” in Q, isn’t that funny?) get mapped when called with a list as an argument.

```q)(3+)4
7
q) (3+)(1;2;3)
4 5 6
q)```

This approach causes problems though when we want to map a function that works both for atoms and lists. One such function is `enlist`, which creates a singleton list in Q, kind of like Haskell’s `return` in the list monad.

```(enlist 3)
3```

So how can we map `enlist` over a list? Just calling it on a list gives a singleton list with the argument as the only element of the result:

```q) count (enlist (1;2;3))
1```

The only solution I can see is to use a trick with folding similar to the one in the definition of `replicate` above.

```map: { [f;xs]
a: {x, (enlist z[y])};
() a[ ; ;f]/ xs
}```

This works:

```q)map[enlist; (1;2;3)]
1
2
3```

Tags:

### 2 Responses to “Haskell in Q”

1. Danno Says:

Hi there! Good to see the ranks of Q are getting more programmers oriented functionally.

I’m more of a Haskell enthusiast than serious practitioner, but I have been programming in Q for a while. Thought I’d comment a little on the translations you’ve provided.

There are built in functions for head and tail (first and last).

Intersperse can be more succinctly written as:

intersperse:{raze ((-1 _ y),\:x),-1#y}

This uses the each-left, which works like the apostrophe each adverb, but only across the left join element.

If you’d like to turn a function composition into a function itself, you need only surround it with parentheses. So, for example, zip becomes:

zip:(,’)

Also, there is a built in map function: each

q)enlist each 1 2 3
1
2
3
q)enlist each 1
,1

If you haven’t already, you should email Simon or Charlie about getting access to the K4 list box.

2. slawekk Says:

Intersperse can be more succinctly written as:

intersperse:{raze ((-1 _ y),\:x),-1#y}

This works only of you intersperse an atom into a list. If you intersperse a list into a list of lists it doesn’t do the right thing:

```q)intersperse [(0;0);((1;1);(2;2);(3;3))]
1 1 0 0 2 2 0 0 3 3
```

Also `zip:(,’)` zips correctly only lists of atoms.

```q)zip:(,')
q)first first zip [((1;1);(2;2);(3;3)); ((4;4);(5;5);(6;6))]
1
q)zip: { x {(x;y)}' y }
q)first first zip [((1;1);(2;2);(3;3)); ((4;4);(5;5);(6;6))]
1 1
```

This site uses Akismet to reduce spam. Learn how your comment data is processed.