How to specify tab width for Alex lexer? - haskell

Alex documentation (Chapter 5) says:
You might want Alex to keep track of the line and column number in the
input text, or you might wish to do it yourself (perhaps you use a
different tab width from the standard 8-columns, for example)
But changing tab width from 8 to 4 in Alex position tracker is rather hard than easy. The code for this is hidden deep inside Alex generated routines:
-- this function is used by `alexGetByte`, which is used by `alex_scan_tkn`, which is
-- used by `alexScanUser` and `alexRightContext`,
-- which is used by `alex_accept` etc etc...
alexMove :: AlexPosn -> Char -> AlexPosn
alexMove (AlexPn a l c) '\t' = AlexPn (a+1) l (((c+7) `div` 8)*8+1)
alexMove (AlexPn a l c) '\n' = AlexPn (a+1) (l+1) 1
alexMove (AlexPn a l c) _ = AlexPn (a+1) l (c+1)

One idea is to create your own wrapper which defines alexMove the way you want it.
On my Mac wrappers are installed in /Library/Haskell/ghc-7.6.3/lib/alex-3.0.5/share/
Look for where files named "AlexWrapper-monad", "AlexWrapper-monad-bytestring", ... reside on your system.
The "-t" command line option tells alex where to look for templates, but it also might pertain to wrappers since it appears that wrappers and templates reside in the same directory.

Related

How to define all musical note names .. Cbb Cb C Cs Css .. as constructors in Haskell

I was playing with musical note names having the goal to not confuse enharmonic equals, i.e. I wanted to get the accidentals (sharps and flats) right. The note a perfect fifth above the note B needs to be Fs and not Gb, even though Fs and Gb are the same key on a piano keyboard.
Also I wanted the convenience of writing e.e. Fs in a haskell program, without spaces, quotes or an extra function.
I ended up defining 35 constructors, ranging from Cbb to Bss. While this worked and did get the accidentals right, I was unhappy about the limitation to at most two accidentals. Internally, the accidentals we represented asInts anyways.
Is there a way to define an infinite number of constructors as indicated in the title, so notes with any number of accidentals (like Cbbbb) could be used? Template haskell maybe?
Or alternatively, can I get the convenience of writing Cbbbb in a haskell program (without quotes, spaces or an extra function) without making Cbbbb a constructor?
I agree with Carsten that actually having lots of disperate constructors like that is a bad idea. It's much more sensible to use data like
data BaseNote = C | D | E | F | G | A | B
data PitchClass = PitchClass
{ baseNote :: BaseNote
, accidentals :: Int }
data Note = Note
{ pitchClass :: PitchClass
, octave :: Int }
As for
Also I wanted the convenience of writing e.e. Fs in a haskell program, without spaces, quotes or an extra function.
you have multiple options.
You could use -XPatternSynonyms. This lets you procure matchable constructors for already-defined data types.
{-# LANGUAGE PatternSynonyms #-}
pattern Cn = PitchClass C 0
pattern Cs = PitchClass C 1
pattern Cb = PitchClass C (-1)
...
These can be provided by a TemplateHaskell macro to avoid code duplication.
You could provide a function that makes it look as compact as single constructor names, but actually isn't.
(♮), (♯), (♭) :: BaseNote -> Int -> Note
bn♮octv = Note (PitchClass bn 0) octv
bn♯octv = Note (PitchClass bn 1) octv
bn♭octv = Note (PitchClass bn (-1)) octv
Now you can write things like
[A♮2, A♮2, C♯3, C♯3, D♮3, D♮3, C♯3]
TBH I don't think either of these is really good though. IMO it makes more sense to specify musical material not in absolute pitches at all, but rather as a sequence of either scale degrees or interval steps.

Error message generating for every input for an empty list case

I'm doing my second assignment in my first semester of learning coding using haskell, so I'm quite new to coding. My problem is that every input I test, empty or not, generates my error message for the empty case, why would this be?
Type classes added for clarity. This is also part of an assignment so please only guide me for this one error :')
type Histogram a = Map a Int
inc :: Ord a => Histogram a -> a -> Histogram a
create
:: Ord a
=> Histogram a -> [a] -> Histogram a
create h (head:restOfString) = create (inc h head) restOfString
create h [head] = inc h head
create h [] = error "No elements in string"
This is wrong:
create h (head:restOfString) = ...
create h [head] = ...
when passing a list containing only one element, the first branch matches, with restOfString being empty. Hence, the second branch will never be taken.
Put the second line first.
If you turn on warnings with -Wall, GHC warns about many potential problems, including this one. I recommend it.
Your first two patterns overlap, so the first one always takes precedence over the second one. Swap them.
This triggers a warning by default in GHC, remember to read the compiler's output. For a better coding experience, it is also advisable to enable -Wall.

G-machine, (non-)strict contexts - why case expressions need special treatment

I'm currently reading Implementing functional languages: a tutorial by SPJ and the (sub)chapter I'll be referring to in this question is 3.8.7 (page 136).
The first remark there is that a reader following the tutorial has not yet implemented C scheme compilation (that is, of expressions appearing in non-strict contexts) of ECase expressions.
The solution proposed is to transform a Core program so that ECase expressions simply never appear in non-strict contexts. Specifically, each such occurrence creates a new supercombinator with exactly one variable which body corresponds to the original ECase expression, and the occurrence itself is replaced with a call to that supercombinator.
Below I present a (slightly modified) example of such transformation from 1
t a b = Pack{2,1} ;
f x = Pack{2,2} (case t x 7 6 of
<1> -> 1;
<2> -> 2) Pack{1,0} ;
main = f 3
== transformed into ==>
t a b = Pack{2,1} ;
f x = Pack{2,2} ($Case1 (t x 7 6)) Pack{1,0} ;
$Case1 x = case x of
<1> -> 1;
<2> -> 2 ;
main = f 3
I implemented this solution and it works like charm, that is, the output is Pack{2,2} 2 Pack{1,0}.
However, what I don't understand is - why all that trouble? I hope it's not just me, but the first thought I had of solving the problem was to just implement compilation of ECase expressions in C scheme. And I did it by mimicking the rule for compilation in E scheme (page 134 in 1 but I present that rule here for completeness): so I used
E[[case e of alts]] p = E[[e]] p ++ [Casejump D[[alts]] p]
and wrote
C[[case e of alts]] p = C[[e]] p ++ [Eval] ++ [Casejump D[[alts]] p]
I added [Eval] because Casejump needs an argument on top of the stack in weak head normal form (WHNF) and C scheme doesn't guarantee that, as opposed to E scheme.
But then the output changes to enigmatic: Pack{2,2} 2 6.
The same applies when I use the same rule as for E scheme, i.e.
C[[case e of alts]] p = E[[e]] p ++ [Casejump D[[alts]] p]
So I guess that my "obvious" solution is inherently wrong - and I can see that from outputs. But I'm having trouble stating formal arguments as to why that approach was bound to fail.
Can someone provide me with such argument/proof or some intuition as to why the naive approach doesn't work?
The purpose of the C scheme is to not perform any computation, but just delay everything until an EVAL happens (which it might or might not). What are you doing in your proposed code generation for case? You're calling EVAL! And the whole purpose of C is to not call EVAL on anything, so you've now evaluated something prematurely.
The only way you could generate code directly for case in the C scheme would be to add some new instruction to perform the case analysis once it's evaluated.
But we (Thomas Johnsson and I) decided it was simpler to just lift out such expressions. The exact historical details are lost in time though. :)

Translate list comprehension to Prolog

I have a list comprehension in Haskell that I want to translate to Prolog.
The point of the list comprehension is rotating a 4 by 4 grid:
rotate :: [Int] -> [Int]
rotate grid = [ grid !! (a + 4 * b) | a <- [0..3], b <- [0..3] ]
Now in Prolog, I translated it like this:
rotateGrid([T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15],
[T0,T4,T8,T12,T1,T5,T9,T13,T2,T6,T10,T14,T3,T7,T11,T15]).
Can we do better?
We can use findall/3 for list comprehensions (Cf. the SWI-Prolog Documentation). E.g.,
?- findall(X, between(1,10,X), Xs).
Xs = [1,2,3,4,5,6,7,8,9,10]
Xs is a list holding all values that can unify with X when X is a number between 1 and 10. This is roughly equivalent to the Haskell expression let Xs = [x | x <- [1..10]](1). You can read a findall/3 statement thus: "find all values of [First Argument] such that [Conditions in Second Argument] hold, and put those values in the list, [Third Argument]".
I've used findall/3 to write a predicate rotate_grid(+Grid, ?RotatedGrid). Here is a list of the approximate Haskell-Prolog equivalences I used in the predicate; each line shows the relation between the value that the Haskell expression will evaluate to and the Prolog variable with the same value:
a <- [0..3] = A in between(0, 3, A)
b <- [0..3] = B in between(0, 3, B)
(a + 4 * d) = X in X is A + 4 * D
<Grid> !! <Index> = Element in nth0(Index, Grid, Element)
Then we simply need to find all the values of Element:
rotate_grid(Grid, RotatedGrid) :-
findall( Element,
( between(0,3,A),
between(0,3,B),
Index is A + 4 * B,
nth0(Index, Grid, Element) ),
RotatedGrid
).
To verify that this produces the right transformation, I down-cased the Prolog code from the question and posed the following query:
?- rotate_grid([t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15],
[t0,t4,t8,t12,t1,t5,t9,t13,t2,t6,t10,t14,t3,t7,t11,t15]).
| true.
Footnotes:
(1): between/3 isn't actually the analogue of [m..n], since the latter returns a list of values from m to n where between(M,N,X) will instantiate X with each value between M and N (inclusive) on backtracking. To get a list of numbers in SWI-Prolog, we can use numlist(M,N,Ns). So a stricter analogue for x <- [1.10] would be the conjunction member(X, Ns), numlist(1, 10, Ns).
You want a permutation of a list. The concrete elements are not considered. Therefore, you can generalize your Haskell signature to
rotate :: [x] -> [x]
This is already a very valuable hint for Prolog: the list's elements will not be considered - elements will not even be compared. So a Prolog solution should be able to handle variables directly, like so:
?- rotateGrid(L,R).
L = [_A,_B,_C,_D,_E,_F,_G,_H,_I,_J,_K,_L,_M,_N,_O,_P],
R = [_A,_E,_I,_M,_B,_F,_J,_N,_C,_G,_K,_O,_D,_H,_L,_P].
And your original definition handles this perfectly.
Your version using list comprehensions suggests itself to be realized via backtracking, certain precautions have to be taken. Using findall/3, as suggested by #aBathologist will rename variables:
?- length(L,16),rotate_grid(L,R).
L = [_A,_B,_C,_D,_E,_F,_G,_H,_I,_J,_K,_L,_M,_N,_O,_P],
R = [_Q,_R,_S,_T,_U,_V,_W,_X,_Y,_Z,_A1,_B1,_C1,_D1,_E1,_F1].
The built-in predicate bagof/3 addresses this problem. Note that we have to declare all local, existential variables explicitly:
rotate_grid2(Grid, RotatedGrid) :-
bagof(
Element,
A^B^Index^ % declaration of existential variables
( between(0,3,A),
between(0,3,B),
Index is A + 4 * B,
nth0(Index, Grid, Element)
),
RotatedGrid).
For lists that are shorter than 16 elements, the Haskell version produces a clean error, but here we get pretty random results:
?- L=[1,2,3,4],rotate_grid(L,R).
L = [1,2,3,4], R = [1,2,3,4].
?- L=[1,2,3,4,5],rotate_grid(L,R).
L = [1,2,3,4,5], R = [1,5,2,3,4].
This is due to the unclear separation between the part that enumerates and "generates" a concrete element. The cleanest way is to add length(Grid, 16) prior to the goal bagof/3.
List comprehensions in Prolog
Currently, only B-Prolog offers a form of list comprehensions:
R#=[E: A in 0..3,B in 0..3,[E,I],(I is A+4*B,nth0(I,L,E))].
However, it does not address the second problem:
| ?- L = [1,2,3], R#=[E: A in 0..3,B in 0..3,[E,I],(I is A+4*B,nth0(I,L,E))].
L = [1,2,3]
R = [1,2,3]
yes
Use a loop predicate foreach/4
If the comprehension should retain variables, which is for example important in constraint programming, a Prolog system could offer a predicate foreach/4. This predicate is the DCG buddy of foreach/2.
Here is how variables are not retained via findall/3, the
result R contains fresh variables according to the ISO
core semantics of findall/3:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.1)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- functor(L,foo,5), findall(X,
(between(1,5,N), M is 6-N, arg(M,L,X)), R).
L = foo(_5140, _5142, _5144, _5146, _5148),
R = [_5210, _5204, _5198, _5192, _5186].
And here is how variables can be retained via foreach/4,
the resulting list has the same variables as the compound
we started with:
Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland
?- [user].
helper(N,L) --> [X], {M is 6-N, arg(M,L,X)}.
Yes
?- functor(L,foo,5), foreach(between(1,5,N),helper(N,L),R,[]).
L = foo(_A,_G,_M,_S,_Y),
R = [_Y,_S,_M,_G,_A]
Using foreach/4 instead of bagof/3 might seem a little bit over the top. foreach/4 will probably only show its full potential when implementing Picat loops, since it can build up constraints, what bagof/3 cannot do.
foreach/4 is an implementation without the full materialization of all solution that are then backtracked. It shares with bagof/3 the reconstruct of variables, but still allows backtracking in the conjunction of the closures.

Haskell and Vim: Proper Indentation

Search for "vim haskell indent" on SO. There are lot of answers for how to configure Vim for Haskell indentation. None of them really "work". They don't provide code as is recommended by the Haskell indentation wiki page. For example, alignment of statements in a do or let block, the = and | of a data type, etc.
Does a Vim solution exist that generates code like the wiki?
This might not be the answer your are looking for, but there is a way you can follow the indentation wiki guide and be compatible with most editors.
For example, do-blocks
Instead of
myFunc x = do y <- bar
return $ x + y
You can indent it like this
myFunx x = do
y <- bar
return $ x + y
This is explicitly mentioned as an acceptable alternative in the indentation wiki.
In the same way, you can format data types
data FooBar
= Foo
| Bar
| Asdf
Guards
myFunc x
| x < 0 = 0
| otherwise = x
Where-clauses
myFunc x = x + y + c where
y = x + 5
c = x * y
And so on...
I personally started to use this kind of style because, like you said, no editor could reliable indent the code otherwise. This works better in all editors, as the indentation is always a multiple of four (or whatever else you pick for your base indentation level). As I used this style, I also started to prefer this consistent indentation level visually, so I wouldn't go back at this point even if editors got smarter.

Resources