Sort abstract data types in Haskell

For example, I have the following:

type something = (Float, Float, Int, Aa, Bb, Cc, Int) 

If I wanted to find the smallest something in the database before their first element (Float), how could I do this? The way I reasoned is the following, but I cannot figure out how to implement it.

Since I have a list of somethings , the easiest way is to create my own helper function min , which compares 2 somethings and returns the smallest of the two. However, he is trying to make this "easier way" that made me depend on type compilation errors ...

 findMin :: something -> something -> somthing findMin xy = sortBy (compare `on` fst) xy 

I am not familiar with sortBy and compare on , I just came across a similar question here in SO, but I was not able to get it to work. As a newbie to Haskell, is there any other way to approach this ?.

+6
source share
3 answers

Using a custom data type is usually the best option, but if you really want to use tuples, you can start by defining a comparingFst helper function that compares based on the first element of the tuple.

 import Data.Ord import Data.List -- Dummy data types for example purposes. Derive from Show just so -- that the example can be more easily tested interactively in ghci. data Aa = Aa deriving Show data Cc = Cc deriving Show type Something = (Float, Float, Int, Aa, Cc, Int) comparingFst :: Something -> Something -> Ordering comparingFst = comparing fstSomething where fstSomething (x,_,_,_,_,_) = x 

Now you can take the smaller of the two elements with:

 findMin :: Something -> Something -> Something findMin xy = case comparingFst xy of LT -> x _ -> y 

or from the list of items

 findMinimum :: [Something] -> Something findMinimum = minimumBy comparingFst 

And you can also use the same helper function to sort:

 sortSomethings :: [Something] -> [Something] sortSomethings = sortBy comparingFst 

In addition, it is worth mentioning that, by default, tuples are compared by elements, starting from the first element, so if your types Aa and Bb can be obtained from Ord and Eq , you do not need anything extra, i.e. an example becomes:

 import Data.List data Ab = Ab deriving (Show, Ord, Eq) data Cc = Cc deriving (Show, Ord, Eq) type Something = (Float, Float, Int, Ab, Cc, Int) findMin :: Something -> Something -> Something findMin xy = min xy findMinimum :: [Something] -> Something findMinimum = minimum sortSomethings :: [Something] -> [Something] sortSomethings = sort 

In other words, you can just use the standard min and sort as-is functions.

+5
source

If you want to compare based on the first data type field, you can let Haskell write code for you:

 data Something = Something Float Float Int String Bool Char Int deriving (Eq, Ord) 

The deriving clause indicates which class class implementations are automatically generated for the type Something . Here we derive Eq , which allows us to ask if two Something (for example, c == ) and Ord are equal, which allows us to compare two Something and know which one is β€œbigger”.

Haskell's default behavior when displaying Ord is to compare each field from first to last, so the default code will begin by comparing the first Float each Something that you want.

Once you are dealing with a type that implements Ord , you can use all sorts of built-in functions, such as minimum :: Ord a => [a] -> a . This takes a list of any type that implements Ord and returns the smallest element. So, as an example:

 st1 = Something 3.14 2.72 7 "hello" False 'Ξ»' 42 st2 = Something 3.15 2.72 7 "hello" False 'Ξ»' 42 smallest = minimum [st1,st2] 
+6
source

Firstly, you have syntax errors.

There are two things you can do. Firstly, following the model of using the accessor function to get the desired field ( fst ), we can define labels for the fields of your type:

 data Something = Something { field_x, field_y :: Float, field_z :: Int } 

and then sort by field_x

 import Data.List import Data.Function sortSomethings :: [Something] -> [Something] sortSomethings = sortBy (compare `on` field_x) 

getting the minimum value is the same as casting a head from a sorted list:

 minSomethings :: [Something] -> Something minSomethings = head . sortSomethings 

you can write your own Ord instance for the Something type, which only compares values ​​with field_x , and then the regular sort and minimum (and other Ord functions), "just work."

+5
source

Source: https://habr.com/ru/post/886842/


All Articles