score:16

*Accepted answer*

**Edit 2**:

While thinking about the `cataX`

method, I figured out that `cataX`

is nothing else than a plain and simple fold. Using that, we can get a pure scala solution without any additional libraries.

So, here it is:

```
( (amt /: floor)(_ max _) /: cap)(_ min _)
```

which is the same as

```
cap.foldLeft( floor.foldLeft(amt)(_ max _) )(_ min _)
```

(not that this is necessarily easier to understand).

I think you can’t have it any shorter than that.

For better or worse, we can also solve it using scalaz:

```
floor.map(amt max).getOrElse(amt) |> (m => cap.map(m min).getOrElse(m))
```

or even:

```
floor.cata(amt max, amt) |> (m => cap.cata(m min, m))
```

As a ‘normal’ Scala programmer, one might not know about the special Scalaz operators and methods used (`|>`

and `Option.cata`

). They work as follows:

`value |> function`

translates to `function(value)`

and thus `amt |> (m => v fun m)`

is equal to `v fun amt`

.

`opt.cata(fun, v)`

translates to

```
opt match {
case Some(value) => fun(value)
case None => v
}
```

or `opt.map(fun).getOrElse(v)`

.

See the Scalaz definitions for `cata`

and `|>`

.

A more symmetric solution would be:

```
amt |> (m => floor.cata(m max, m)) |> (m => cap.cata(m min, m))
```

**Edit:** Sorry, it’s getting weird now, but I wanted to have a point-free version as well. The new `cataX`

is curried. The first parameter takes a binary function; the second is a value.

```
class CataOption[T](o: Option[T]) {
def cataX(fun: ((T, T) => T))(v: T) = o.cata(m => fun(m, v), v)
}
implicit def option2CataOption[T](o: Option[T]) = new CataOption[T](o)
```

If `o`

matches `Some`

we return the function with the value of `o`

and the second parameter applied, if `o`

matches `None`

we only return the second parameter.

And here we go:

```
amt |> floor.cataX(_ max _) |> cap.cataX(_ min _)
```

Maybe they already have this in Scalaz…?

score:0

I'm adding another answer which was inspired by both *retronym* and *Debilski* - basically it amounts to converting the cap and floor to functions (`Double => Double`

, if they are present) and then folding the identity function through them with composition:

```
def restrict(floor: Option[Double], cap: Option[Double], amt: Double) = {
(identity[Double] _ /: List(floor.map(f => (_: Double) max f), cap.map(c => (_: Double) min c)).flatten){ _ andThen _ }(amt)
}
```

score:0

Straightforward solution with plain Scala and anonymous lambda, without any mappings, folds, Double.{Min/Max}Value, and so on:

```
def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double =
((x:Double) => x min cap.getOrElse(x))(amt max floor.getOrElse(amt))
```

score:0

I like the initial solution with the match-case most - beside the fact, that I didn't understand that `amt`

means `amount`

(in Germany, 'amt' means 'office') and I only knew `cap`

as something I wear on my head ...

Now here is a really uninspired solution, using an inner method:

```
def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double = {
def restrict (floor: Double, cap: Double, amt: Double) =
(floor max amt) min cap
var f = floor.getOrElse (amt)
val c = cap.getOrElse (amt)
restrict (f, c, amt)
}
```

score:1

This is another way to fix Landei's first answer

```
def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double = {
val chopBottom = (floor.getOrElse(amt) max amt)
chopBottom min cap.getOrElse(chopBottom)
}
```

score:2

This isn't really much easier in Scalaz than in regular Scala:

```
def restrict(floor: Option[Double], cap: Option[Double], amt: Double) =
floor.map(amt max).orElse(Some(amt)).map(x => cap.map(x min).getOrElse(x)).get
```

(Add `_`

after `max`

and `min`

if it makes you feel better to see where the parameter goes.)

Scalaz is a little easier to read, though, once you understand what the operators do.

score:2

I find that when a question asks to use an `Option`

to indicate an optional parameter, there's usually a more natural way to represent the missing parameter. So I'm going to change the interface a little here, and use default arguments to define the function and named parameters to call the function.

```
def restrict(amt:Double,
floor:Double = Double.NegativeInfinity,
cap:Double=Double.PositiveInfinity):Double =
(amt min cap) max floor
```

Then you can call:

```
restrict(6)
restrict(6, floor = 7)
restrict(6, cap = 5)
```

score:2

This is based on Ken Bloom's answer:

```
sealed trait Constrainer { def constrain(d : Double) : Double }
trait Cap extends Constrainer
trait Floor extends Constrainer
case object NoCap extends Cap { def constrain(d : Double) = d }
case object NoFloor extends Floor { def constrain(d : Double) = d }
implicit def d2cap(d : Double) = new Cap { def constrain(amt : Double) = d min amt }
implicit def d2floor(d : Double) = new Floor { def constrain(amt : Double) = d max amt }
def restrict(amt : Double, cap : Cap = NoCap, floor: Floor = NoFloor) : Double = {
cap.constrain(floor.constrain(amt))
//or (cap.constrain andThen floor.constrain) amt
}
```

It ends up with writing code like this:

```
restrict(amt, cap = 5D)
restrict(amt, floor = 0D)
```

I think that's pretty awesome and doesn't suffer from the problem with Ken's solution (in my opinion), which is that it is a *hack*!

score:4

~~How about this?~~

```
//WRONG
def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double =
(floor.getOrElse(amt) max amt) min cap.getOrElse(amt)
```

[Edit]

Second try:

```
def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double =
floor.map(f => f max _).getOrElse(identity[Double] _)(
cap.map(c => c min _).getOrElse(identity[Double] _)(amt))
```

Looks a little bit too "lispy" for my taste, but passes the tests :-)

[2nd Edit]

The first version can be "repaired", too:

```
def restrict(floor: Option[Double], cap: Option[Double], amt: Double): Double =
(floor.getOrElse(-Double.MaxValue) max amt) min cap.getOrElse(Double.MaxValue)
```

score:4

Not prettier, not much shorter, and certainly not faster! But it is more composable more generic and more "functional":

**EDIT**: made the code fully generic :)

```
def optWith[T](a: Option[T], b: T)(op:(T,T)=>T) =
a map (op(b,_)) getOrElse b
def optMin[T:Numeric](a: Option[T]) =
(b:T) => optWith(a, b)(implicitly[Numeric[T]].min)
def optMax[T:Numeric](a: Option[T]) =
(b:T) => optWith(a, b)(implicitly[Numeric[T]].max)
def restrict[T,FT,CT](x:T, floor:Option[FT], ceil:Option[CT])
(implicit ev:Numeric[T], fv:FT=>T, cv:CT=>T) =
optMin(ceil map cv) compose optMax(floor map fv) apply(x)
```

**UPDATE 2**: There's also this version, taking better advantage of `Numeric`

```
def optWith[T](a: Option[T])(op:(T,T)=>T) =
(b:T) => a map (op(b,_)) getOrElse b
def restrict[T,FT,CT](x:T, floor:Option[FT], ceil:Option[CT])
(implicit n:Numeric[T], fv:FT=>T, cv:CT=>T) =
optWith(ceil map cv)(n.min) compose optWith(floor map fv)(n.max) apply(x)
```

I hope you like type signatures :)

**UPDATE 3**: Here's one that does the same with *bounds*

```
def optWith[T, V <% T](op:(T,T)=>T)(a: Option[V]) =
(b:T) => a map (op(b,_)) getOrElse b
def restrict[T:Numeric, FT <% T, CT <% T]
(floor:Option[FT], ceil:Option[CT], amt:T) = {
val n = implicitly[Numeric[T]]; import n._
optWith(min)(ceil) compose
optWith(max)(floor) apply(amt)
}
```

If nothing else... this shows quite clearly why import parameters would be a Good Thing(tm). Imagine if the following was valid code:

```
def optWith[T, V <% T](op:(T,T)=>T)(a: Option[V]) =
(b:T) => a map (op(b,_)) getOrElse b
def restrict[import T:Numeric,FT <% T,CT <% T]
(floor:Option[FT], ceil:Option[CT], amt:T) = {
optWith(min)(ceil) compose
optWith(max)(floor) apply(amt)
}
```

**UPDATE 4**: Turning the solution upside down here. This one offers some more interesting possibilities for future extension.

```
implicit def optRhs[T:Ordering](lhs:T) = new Object {
val ord = implicitly[Ordering[T]]; import ord._
private def opt(op: (T,T)=>T)(rhs:Option[T]) =
rhs map (op(lhs,_)) getOrElse lhs
def max = opt(ord.max) _
def min = opt(ord.min) _
}
def restrict[T : Ordering](floor:Option[T], cap:Option[T], amt:T) =
amt min cap max floor
```

With any luck, I'll inspire someone else to build a better solution out of mine. That's how these things usually work out...

score:5

I'll start with this:

```
def restrict(floor : Option[Double], cap : Option[Double], amt : Double) : Double = {
val flooring = floor.map(f => (_: Double) max f).getOrElse(identity[Double] _)
val capping = cap.map(f => (_: Double) min f).getOrElse(identity[Double] _)
(flooring andThen capping)(amt)
}
```

But I have the feeling I'm missing some opportunity here, so I may not be finished.

score:5

Rather than going for pure brevity, this shows how much easier composition becomes if you turn `cap`

and `floor`

into functions.

```
scala> val min = (scala.math.min _).curried
min: (Int) => (Int) => Int = <function1>
scala> val max = (scala.math.max _).curried
max: (Int) => (Int) => Int = <function1>
scala> def orIdentity[A](a: Option[A])(f: A => A => A): (A => A) = a ∘ f | identity
orIdentity: [A](a: Option[A])(f: (A) => (A) => A)(A) => A
scala> val cap = 5.some; val floor = 1.some
cap: Option[Int] = Some(5)
floor: Option[Int] = Some(1)
scala> val ffloor = orIdentity(floor)(max)
ffloor: (Int) => Int = <function1>
scala> val fcap = orIdentity(cap)(min)
fcap: (Int) => Int = <function1>
scala> val capAndFloor = fcap ∘ ffloor
capAndFloor: (Int) => Int = <function1>
scala> (0 to 8).toSeq ∘ (capAndFloor)
res0: Seq[Int] = Vector(1, 1, 2, 3, 4, 5, 5, 5, 5)
```

From scalaz, I use `MA#∘`

, the functor map, both as a way of using `Option.map`

and `Function1.andThen`

; and `OptionW#|`

which is an alias for `Option.getOrElse`

.

**UPDATE**

This is what I was looking for:

```
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> val min = (scala.math.min _).curried
min: (Int) => (Int) => Int = <function1>
scala> val max = (scala.math.max _).curried
max: (Int) => (Int) => Int = <function1>
scala> def foldMapEndo[F[_]: Foldable, A](fa: F[A], f: A => A => A): Endo[A] =
| fa.foldMap[Endo[A]](a => f(a))
foldMapEndo: [F[_],A](fa: F[A],f: (A) => (A) => A)(implicit evidence$1: scalaz.Foldable[F])scalaz.Endo[A]
scala> val cap = 5.some; val floor = 1.some
cap: Option[Int] = Some(5)
floor: Option[Int] = Some(1)
scala> val capAndFloor = List(foldMapEndo(floor, max), foldMapEndo(cap, min)) ∑
capAndFloor: scalaz.Endo[Int] = scalaz.Endos$$anon$1@4352d1fc
scala>(0 to 10).toSeq.map(capAndFloor)
res0: Seq[Int] = Vector(1, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5)
```

`scalaz.Endo[A]`

is a wrapper around `A => A`

, there are implicit conversions in both directions. There is an instance of `Monoid`

defined for `Endo[A]`

, `Monoid#plus`

chains the functions, and `Monoid#zero`

returns the identity function. If we have a `List`

of `Endo[A]`

, we can sum the list and result in a single value, which can be used as `A => A`

.

`MA#foldMap`

maps the given function over a `Foldable`

data type, and reduces to a single value with a `Monoid`

. `foldMapEndo`

is a convenience on top of this. This abstraction allows you to easily change from proving the cap and floor in `Option`

s to any foldable type, such as a `List`

.

```
val capAndFloor = Seq(foldMapEndo(List(1, 2, max), foldMapEndo(cap, min)).collapsee
capAndFloor: scalaz.Endo[Int] = scalaz.Endos$$anon$1@76f40c39
```

Another refactoring might lead to:

```
val capAndFloor = Seq((cap, min), (floor, max)).foldMap { case (a, f) => foldMapEndo(a, f) }
capAndFloor: scalaz.Endo[Int] = scalaz.Endos$$anon$1@25b85c8e
```

score:15

Not quite as terse as the scalaz version, but on the other hand, no dependencies,

```
List(floor.getOrElse(Double.NegativeInfinity), cap.getOrElse(Double.PositiveInfinity), amt).sorted.apply(1)
```

Source: stackoverflow.com

#### Related Query

- Scala functional programming gymnastics
- Difference between reduce and foldLeft/fold in functional programming (particularly Scala and Scala APIs)?
- Functional Reactive Programming in Scala
- Is Scala functional programming slower than traditional coding?
- Real World Functional Programming in Scala
- Is Scala a Functional Programming Language?
- Functional Queue From Programming In Scala
- How to enforce Functional Programming on Scala
- An example of functional programming in scala
- Coursera - Functional Programming Principles in Scala - can't work with example project because of errors
- Functional programming in scala - infinite streams
- Generic programming & Rotten Bananas in Scala involving functional dependencies
- How to rewrite this code in Scala using a Functional Programming approach
- What is a combinator in Scala or functional programming
- Functional Programming scala
- Need help to refactor this scala method in functional programming style
- Functional Programming in Scala - Building the Option Type
- Scala way of merging tuples in a list using functional programming techniques
- Scala Functional Programming Generics
- How to create a List of Lists in Scala in functional programming style
- How to manage DB connection in Scala using functional programming style?
- Functional Programming exercise with Scala
- Choosing between side effects and good API design in functional programming with scala
- What is used for a 2D board in functional programming with Scala
- How to implement db operation in scala functional programming
- How are the columns and rows counted in pascal function in Functional Programming Principles in Scala at coursera?
- Scala functional programming with vectors
- Scala functional programming operator :::
- Scala functional programming and mutability
- Scala functional programming - transform java like code to functional code

#### More Query from same tag

- Java spark example runs wrong with error: java.lang.NoSuchMethodError: scala.Predef$.$scope()Lscala/xml/TopScope$
- Can JetGradle Be Used In IntelliJ 12 Alongside Gradle Generated Project Files That Have Scala Facets?
- Unit testing spark streaming
- Scala error: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class scala.Some
- sbt equivalent of gradle's JavaExec
- Spark: driver/worker configuration. Does driver run on Master node?
- As I am defining classes in scala, The controls is then not going inside the main function. What to do?
- Scala XML, Get nodes where parent has attribute value match
- Option[_] of Type with Play Json
- Uses of the type class and difference between type class and type trait
- Using logback with Akka
- How to make trait contravariant when its type parameter appears in an invariant position?
- Akka Supervision default behavior
- Can application config be loaded in a scala macro?
- Scala refactoring duplicate code
- Installing the scala android eclipse plugin
- Scala Spark setting schema duplicates columns
- Value assigned to type member via method type parameter breaks type equivalence
- Why won't scalatest compile?
- SBT transitive dependency resolution conflict
- Deadbolt authorization based on parameters
- What does ?~> meaning in the scala programming language?
- How to sample from a Scala array efficiently
- Spray multiple post parameters
- Using Composite Keys with Salat and MongoDB
- How does mapValues translate to parallel collections in Scala
- Unit test to check retrievals from config file
- Akka remote : trying to connect two machines
- Scala for Junior Programmers?
- Match on tuples within for comprehension