1

I have a function that gets a List and has to return the smallest Element of it.

Unfortunately I keep getting the issue:

Parse error in pattern: minim

What could I have done wrong?

minim :: [Int] -> Int
minim []       = 0
minim [x]      = x
minim x:xs     = min x (minim xs)

min :: Int -> Int -> Int
min a b
    | a > b  = b
    | a < b  = a
Chris Martin
  • 30,334
  • 10
  • 78
  • 137
jublikon
  • 3,427
  • 10
  • 44
  • 82

5 Answers5

10

If you want to solve it the most Haskell way. I would solve it as such:

-- Does not work for empty lists (so maybe needs to be wrapped in some logic)
foldr1 min [-3,1,2,3]
-- Works for empty but needs a "default value" (in this case 0)
foldr min 0 [-3,1,2,3]

If you want to learn by implementing it yourself, then this works for me

minim :: [Int] -> Int
minim []       = 0
minim [x]      = x
minim (x:xs)   = min x (minim xs)

min :: Int -> Int -> Int
min a b
    | a > b  = b
    | a < b  = a
    | a == b = a

I would however make it a bit more safe, because is really 0 the smallest int in the list if it is empty? I think you should use Nothing as the result.

import Data.Maybe

import Prelude hiding (min)

main = print $  minim [1,3,4, 6,6,-9]

minim :: [Int] -> Maybe Int
minim []       = Nothing
minim [x]      = Just x
minim (x:xs)   = min x <$> minim xs

min :: Int -> Int -> Int
min a b
    | a > b  = b
    | a < b  = a
    | a == b = a
Viktor Mellgren
  • 4,318
  • 3
  • 42
  • 75
  • 1
    `0` is a pretty bad initialiser for `min`, don't you think? Maybe `minim [] = 1/0` ? – Mulan Mar 01 '17 at 19:21
  • 1
    The third equation for `minim` is pretty awkward, with the `fromJust` call and another mention of `Just` as well. Better would be: `minim (x:xs) = min x <$> minim xs`. – amalloy Mar 01 '17 at 20:10
  • 1
    @amalloy, thanks for the suggestion, felt that something was strange with having "Just" there, but didn't get it to work. Not very familiar with <$> (or Functors/monads at all) but now i learned something, thanks :) – Viktor Mellgren Mar 02 '17 at 11:47
3

Use minimum.

> minimum [2, 1, 3]
> 1
ivanjermakov
  • 1,131
  • 13
  • 24
0

You have one parameter that you want to match (the list of Ints). Where you want to match parts of that list you need to put these in brackets to show the compiler you are matching one thing. Thus the last pattern should be (x:xs).

dave
  • 4,812
  • 4
  • 25
  • 38
  • Your explanation seems correct and logic to me. Unfortunately for 'minim x:[] = x' I still get error in parse pattern. – jublikon Mar 01 '17 at 11:17
  • @jublikon: my bad I've noticed a second problem! – dave Mar 01 '17 at 11:27
  • 2
    `[x]` is a perfectly fine (a much clearer) way to match a list of one. – Karl Bielefeldt Mar 01 '17 at 12:25
  • @KarlBielefeldt: ah, I hadn't realised that, I've always used the cons operator (so when told that there was a syntax error but not which line that looked wrong to me). – dave Mar 03 '17 at 01:53
  • @dave Many would love to see that misinformation is removed from SO answers. Therefore, I kindly ask you to edit yours accordingly. – Ingo Mar 03 '17 at 07:35
0

here's another way of implementing what you asked but without having to use auxiliary functions such as min

minElem::[Int]->Int
minElem [] = 0
minElem [x] = x
minElem (x:y:xs) 
 |x > y = minElem (y:xs)
 |x < y = minElem (x:xs)
 |x == y = minElem (x:xs)
0

This function should not take lists, because it makes no sense to conjure up a minimum of e.g. 0 for empty lists, when the element type may even be allowing negative values. To have total safety and generality, we can use the Min type. First, let's make an example input value:

exampleList = 1 :| [2, 3, 4]

The :| is the constructor for non-empty lists, which are more suited.

To find the minimum, we can use the sconcat, which combines all elements of a non-empty list using the Semigroup operation, which will in this case be like the min function on two elements shown in other answers.

> sconcat $ fmap Min exampleList
Min {getMin = 1}

To extract the number from the Min, you can use getMin.

Janus Troelsen
  • 20,267
  • 14
  • 135
  • 196