-- step 1-2-3
findKeyLength :: B.ByteString -> [(Int, Double)]
findKeyLength bs =
  let
    -- step 1
    -- "2 to (say) 40"
    keyLenhgths =
      [2..40]

    -- "You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4
    -- KEYSIZE blocks instead of 2 and average the distances."
    numBlocks =
      12

    -- helper function: from bs, take numBlocks blocks with length l
    -- and compute the average hamming distance for these blocks
    distance l =
      blocks numBlocks l bs
      |> computeDistance l

  in
    -- compute the distance for all keylengths
    -- and sort the resuls
    map distance keyLenhgths
    |> List.sortBy (compare `on` snd)
findKeyLength :: B.ByteString -> [(Int, Double)]
findKeyLength bs =
  let
    -- step 1
    -- "2 to (say) 40"
    keyLenhgths =
      [2..40]

    -- "You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4
    -- KEYSIZE blocks instead of 2 and average the distances."
    numBlocks =
      12

    -- helper function: from bs, take numBlocks blocks with length l
    -- and compute the average hamming distance for these blocks
    distance l =
      blocks numBlocks l bs
      |> computeDistance l

  in
    -- compute the distance for all keylengths
    -- and sort the resuls
    map distance keyLenhgths
    |> List.sortBy (compare `on` snd)
findKeyLength bs =
  let
    -- step 1
    -- "2 to (say) 40"
    keyLenhgths =
      [2..40]

    -- "You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4
    -- KEYSIZE blocks instead of 2 and average the distances."
    numBlocks =
      12

    -- helper function: from bs, take numBlocks blocks with length l
    -- and compute the average hamming distance for these blocks
    distance l =
      blocks numBlocks l bs
      |> computeDistance l

  in
    -- compute the distance for all keylengths
    -- and sort the resuls
    map distance keyLenhgths
    |> List.sortBy (compare `on` snd)