CRAP! I confused myself with an invalid test:
exec( http(foo) ) // doesn’t compile
exec( http(foo).get(foo) ) // DOES!!!
Clearly, the http object is not the right type until after you have called one of the method functions. Oops!
Okay, to recap, the reason it didn’t work with a string is because of PEBCAC. My mistake.
I’m still trying to wrap my brain around why it doesn’t work with the function. Let’s see:
val foo : ( Session => Session ) =
(session) => session.set( “foo”, “bar” )
exec( session => session.set( “foo”, “bar” ) ) // works
exec( foo ) // fails
foo is an expression of type (Session=>Session). The parameter to exec that works is also a lambda expression that takes in a session and returns a session. But somehow, Scala knows to transform that one.
Of course, it only knows that
session is a Session because it knows that exec has a form that takes in an Expression[Session], which is a type alias for ( Session => Validation[Session] ). So as it is compiling, it infers the correct type for
session, and infers the expected type for the result, which is Validation[Session]. There must be an implicit somewhere that wraps the session in a Success(), and so it is able to make the necessary conversion at compile time.
Whereas, the type of foo is (Session=>Session). The only way to convert that is to create a wrapper function that calls the function, and wraps the result in a Success(). Since there is no such wrapper available implicitly, the Compiler complains.
So, in my head, applying the substitution principle, it should work. But when you start throwing implicit conversions in there, things don’t work quite the same. Is that why there is a general warning against the indiscriminate use of implicit conversions? Makes the code harder to reason about?
Thanks for helping me understand.