Mapping and sorting lists of Haskell tuples
Mapping over second

It is surprising that you know about &amp;&amp;&amp;, but not second, also from Arrows:

mapOverSnd f = map (second f)


second is of type Arrow a =&gt; a b c -&gt; a (d, b) (d, c), which boils down to (b-&gt;c) -&gt; (d,b) -&gt; (d,c) here.

Alternatively, you can take advantage that pairs are a Functor instance: `fmap (+1) ("...",10) = ("...",11)

mapOverSnd f = map (fmap f)


Definitions can be infix

You wrote (//) a b =, but definitions can be infix, too:

a // b = fromIntegral a / fromIntegral b


your2TupleOrdering

2-tuples are simply called pairs. sort needs a function like compare, so define yours in terms of compare. Take advantage of Ordering being an instance of Monoid:

myPairOrdering (a1,b1) (a2,b2) = compare a1 a2 `mappend` compare b2 b1


The Monoid instance of Ordering is:

mempty = EQ
EQ `mappend` y = y -- only if left side equals, use right
x  `mappend` _ = x -- shortcut otherwise


ngrams

Any solution to ngrams will be ugly because you don't want the very last elements which are below the minimum length. You are forcing an Eq constraint, which is not necessary. Avoid by comparing the length. Another solution is

ngrams' n = filter ((==n).length) . map (take n) . tails


The filter part here is ugly.

The let-chain

You can condense the let-chain with composition, cutting out freq3grams and my3grams. At some point in you haskell journey, you will do that. When you grow wiser, you will value readability over succinctness. Long story short: This part is OK.