简体   繁体   中英

Haskell - I have a question split into 3 parts - using the first 2 functions make a function that sorts a list of tuples on the first elements

New to haskell. So the first function I made sort_by sorts a list of type a using quicksort - works fine.

Next function compare by takes in a comparator type (defined below) and a function and returns a comparator - so GT , EQ etc. Both of these functions I had to make using just the function definition. Now the problem - I'm supposed to use both these functions to define a function based on the title using currying, but I don't know how my compare_By function is supposed to help create a function like that?

Any help greatly appreciated. Thanks.

import GHC.Show (Show)
type Comparator a   = a -> a -> Ordering
type Tokeniser a    = String -> [a]
type Translator a b = a -> Maybe b

data English = E String deriving (Show)
data French  = F String deriving (Show)
data German  = G String deriving (Show)


sort_by :: Comparator a -> [a] -> [a]
sort_by o as = qs as []
    where qs [] as' = as'
          qs (a:as) as' = qs les $ a : qs gts as'
            where les = [a' | a' <- as, a  `o` a' == GT] 
                  gts = [a' | a' <- as, a `o` a' /= GT]

compare_by :: (b -> a) -> Comparator a -> Comparator b
compare_by f o a b = o (f a) (f b)

sort_by_fst :: Comparator a -> [(a,b)] ->[(a,b)]
sort_by_fst f [(a,b)] = ??

When faced with these problems it's helpful to look at the types and work from there.

You need to use sort_by and compare_by to create sort_by_fst . Evidently, we'll need sort_by to sort the list, so let's see the type of that:

sort_by :: Comparator a -> [a] -> [a]

Great, let's use that to sort the list:

sort_by_fst f xs = sort_by _comparator xs

Looking at the type of sort_by again, we can see we need a Comparator (a, b) to sort the xs :: [(a, b)] . But we only have a f :: Comparator a , so use compare_by to get a Comparator (a, b) .

compare_by :: (b -> a) -> Comparator a -> Comparator b
-- Specialising to the types we need (substituting b = (a, b)):
compare_by :: ((a, b) -> a) -> Comparator a -> Comparator (a, b)

In addition to a Comparator a , we need a (a, b) -> a : a function that gets the first element of a tuple. fst does exactly that:

sort_by_fst f xs = sort_by (compare_by fst f) xs

This could also be written more succinctly as

sort_by_fst = sort_by . compare_by fst

By the way, the _name (eg _comparator ) syntax is GHC's typed holes feature . If you compile code with a hole, GHC will tell you what type of expression needs to go there and suggests possible bindings (eg functions and parameters) that could fill the hole.


As a side note, the compare_by function is a specialised and flipped version of on from Data.Function :

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c 

sort_by_fst could therefore be implemented like this:

import Data.List (sortBy)
import Data.Function (on)

sort_by_fst :: Comparator a -> [(a, b)] -> [(a, b)]
sort_by_fst f = sortBy (f `on` fst)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM