In this article, the author explains monad using this example (I am guessing Haskell is used):
bind f' :: (Float,String) -> (Float,String)
which implies that
bind :: (Float -> (Float,String)) -> ((Float,String) ->
(Float,String))
and proceed to ask to implement the function bind and offer the solution as:
bind f' (gx,gs) = let (fx,fs) = f' gx in (fx,gs++fs)
I am having problem understanding the solution. What would this look like in C or Swift?
I have gone as far as I can implementing the example and I am stuck at implementing bind:
let f: Float -> Float = { value in return 2 * value }
let g: Float -> Float = { value in return 10 + value }
let ff: Float -> (Float, String) = { value in return (f(value), "f called") }
let gg: Float -> (Float, String) = { value in return (g(value), "f called") }
In C++ I think it would look something like this:
#include <functional>
#include <string>
#include <utility>
using P = std::pair<float, std::string>;
using FP = std::function<P(P)>;
FP mbind(std::function<P(float)> f) {
return [f](P in) {
auto && res = f(in.first);
return {res.first, in.second + res.second};
};
}
In C you could do something similar by storing function pointers, though the invocation syntax would have to be more verbose since you'll need to pass the state around explicitly.
In Swift, perhaps something like this:
let bind: (Float -> (Float, String)) -> ((Float, String) -> (Float, String)) = {
lhs in
return {
rhs in
let result = lhs(rhs.0)
return (result.0, "\(result.1); \(rhs.1)" )
}
}
It is a bind for Writer monad. The bind function for that monad should do 2 things:
Execute computation with Float value.
Update the existing log (a String value).
Initially you have a tuple (oldFloat,oldString) and want to apply to this tuple a function with type Float -> (Float,String).
Your function takes an oldFloat value from tuple (oldFloat,oldString) and returns a tuple (newFloat,newString).
What behavior do you expect from your bind function? I suppose you want to get a tuple containing a newFloat and updated log oldString ++ new string, right? Here is a straitforward implementation of it:
bind f (oldFloat,oldString) =
-- apply function f to oldFloat from tuple (oldFloat,oldString)
-- to get a new tuple (newFloat,newString)
let (newFloat,newString) = f oldFloat
-- you want from your bind function to get a tuple containing
-- a newFloat and a newString added to oldString
in (newFloat, oldString ++ newString)
Related
I'm an old C programmer. I'm trying to implement some code in Swift and needed a binary search algorithm that would return the closest element if an exact match isn't available.
I searched for a bit and either the code was invoking so many Swift concepts at once as to be opaque to my C eyes or it wasn't suitable for my use case.
I decided to port some old C code to get the job done and wrote the following:
public func bsearch(arr:[Any], target:Double, bcompare:(Any,Double)->Int)-> Int{
// v is array being searched
// target is what we're looking for
// bcompare is a pointer to user-supplied comparison function
// bcompare returns -1 if left element < right element, 0 if =, 1 if >
// target must be same type as v element being compared
// returns index of array element that is closest to <= target
// note! indexed returned may not match target value
var lo, hi, mid:Int
hi = v.count-1
if hi <= 0 {return -1}
lo = 0
while ((hi-lo) > 1) {
mid = (hi+lo)/2
if( bcompare(v[mid], target) == -1){
lo = mid + 1
}
else{
hi = mid
}
}
if bcompare(v[hi],target) == 0{
return hi
}
return lo
}
func eleCompare(left:locArrayele,right:Double)->Int{
if right < left.degrees{
return -1
}
else if right == left.degrees{
return 0
}
else {
return 1
}
}
In C, you can pass search functions pointers to structures and tell the compiler how to interpret the memory blocks in the comparison functions that you also pass to the search function. The comparison function reference is just another memory pointer and no parameters are needed.
I assumed a Swift "Any" declaration was equivalent to a pointer reference and wrote the above code with that idea in mind. The compiler complained about declaring the search target as an Any when the comparison function referred to the target as a double. To satisfy the compiler, I declared the target as a double and the code compiled fine.
My problem now is to actually test the code. No matter how I try to invoke the search function, the compiler is unhappy. This test snippet is the closest I could get to satisfying the compiler.
class locArrayele{
public var degrees = CLLocationDegrees()
public var ix = Int()
init( degrees:CLLocationDegrees, i:Int){
self.degrees = degrees
self.ix = i
}
}
public var latArray : [locArrayele] = []
.
.
.
ix = bsearch(v: latArray, target:35.0, bcompare: eleCompare )
print(" when lat is 35, closest ix is \(ix))
Apparently, the compiler wants me to supply parameters to eleCompare, a task I expect bsearch to do as it executes.
How do I invoke the code? I realize I'm c-ifing Swift but I'm just trying to get something to work. Elegance can come later as I get comfortable in the language.
You need to make your bsearch() generic. You have two types that can vary: the first type is the one that the array v contains, and the other is the target's type.
Change your first line to:
public func bsearch<T, U>(v: [T], target: U, bcompare: (T, U) -> Int) -> Int {
You don't have to use 2 different types when you call it, but you can.
Example: String and Int
This example has an array of words of type [String] and it is searching for the word with 5 letters, so the target in an Int.
let words = ["a", "to", "the", "seven", "butter"]
func compareNameLength(left: String, right: Int) -> Int {
if left.count < right {
return -1
} else if left.count == right {
return 0
} else {
return 1
}
}
// search for the 5 letter word
let i = bsearch(v: words, target: 5, bcompare: compareNameLength)
print(words[i])
seven
Example: Int and Int
This example has an [Int] containing prime numbers, and it is searching for a prime closest to a number without going over, so the target is an Int.
let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
func compareInt(left: Int, right: Int) -> Int {
if left < right {
return -1
} else if left == right {
return 0
} else {
return 1
}
}
// search for closest prime to 8
let p = bsearch(v: primes, target: 8, bcompare: compareInt)
print(primes[p])
7
In my playground in Xcode 9
func somefn<Int>(_ a:[Int])->[Int]{
if(a.count == 1 || a.isEmpty){
return a
}else{
let e1 = (a.count/2) - 1
let s2 = e1 + 1
let lhs = Array(a[...e1])
let rhs = Array(a[s2...])
if lhs.first! > rhs.first! {
print("LHS first is bigger than RHS second")
}
return []
}
}
let s = [1,4,6,9]
somefn(s)
Gives error:
Binary operator '>' cannot be applied to two 'Int' operands
The issue seems to be that the <Int> syntax after the function name is being treated as a generic type placeholder and not the actual data type of Int.
If you replace <Int> with T in the whole function declaration you still get the error.
func somefn<T>(_ a:[T]) -> [T] {
This makes sense since the < operator is now ambiguous. By updating the signature to indicate that T must be a Comparable, the problem goes away:
func somefn<T:Comparable>(_ a:[T]) -> [T] {
You could also do:
func somefn<Int:Comparable>(_ a:[Int]) -> [Int] {
but that's confusing to any reader since that Int is not the data type of Int.
This all assumes you intend to be able to pass arrays of different data types and get back an array of the same type.
If you just want to support an array of Int for both the parameter and return type, change the signature to:
func somefn(_ a:[Int]) -> [Int] {
I am experiencing a boxing issue which affects negatively performance of my Scala code. I have extracted the relevant code, which still shows the issue, with some added strangeness. I have the following representation of a 2D Double array which allows me to perform transformations on it by providing my functions:
case class Container(
a: Array[Array[Double]] = Array.tabulate[Double](10000, 10000)((x,y) => x.toDouble * y)
) {
def transformXY(f: (Double, Double, Double) => Double): Container = {
Container(Array.tabulate[Double](a.length, a.length) { (x, y) =>
f(x, y, a(x)(y))
})
}
def transform(f: Double => Double): Container = {
Container(Array.tabulate[Double](a.length, a.length) { (x, y) =>
f(a(x)(y))
})
}
}
Following code reproduces the issue for me:
object Main extends App {
def now = System.currentTimeMillis()
val iters = 3
def doTransformsXY() = {
var t = Container()
for (i <- 0 until iters) {
val start = now
t = t.transformXY { (x, y, h) =>
h + math.sqrt(x * x + y * y)
}
println(s"transformXY: Duration ${now - start}")
}
}
def doTransforms() = {
var t = Container()
for (i <- 0 until iters) {
val start = now
t = t.transform { h =>
h + math.sqrt(h * h * h)
}
println(s"transform: Duration ${now - start}")
}
}
if (true) { // Shows a lot of boxing if enabled
doTransformsXY()
}
if (true) { // Shows a lot of boxing again - if enabled
doTransformsXY()
}
if (true) { // Shows java8.JFunction...apply()
doTransforms()
}
if (true) { // Shows java8.JFunction...apply() if doTransforms() is enabled
doTransformsXY()
}
}
When I run this code and sample it using Java VisualVM, I experience the following:
while doTransformsXY is running, I see a lot of time spent in scala.runtime.BoxesRunTime.boxToDouble()
once doTransforms is running, there is no more significant time spend it boxing, samples show scala.runtime.java8.JFunction2$mcDII$sp.apply() instead
I run doTransformsXY again, there is still no significant boxing, again time grows in scala.runtime.java8.JFunction2$mcDII$sp.apply()
This is with Scala 2.12.4, Windows x64 jdk1.8.0_92
My primary question is about the boxing, which I see in my production code as well:
why is there Double boxing happening in Array.tabulate? Do I need to go procedural (while loops, manual Array creation) to avoid it?
My secondary question is:
why is no more boxing done once I call the transform variant?
why is no more boxing done once I call the transform variant?
I did not reproduce that. If I carefully pause VMs and check with JProfiler, it still does a lot of boxing and allocation of Doubles. Which is what I expected, and I have an explanation for.
Looking at the Function1 and Function2 traits in standard library, we can see #specialized annotations:
trait Function1[#specialized(Int, Long, Float, Double) -T1, #specialized(Unit, Boolean, Int, Float, Long, Double) +R]
trait Function2[#specialized(Int, Long, Double) -T1, #specialized(Int, Long, Double) -T2, #specialized(Unit, Boolean, Int, Float, Long, Double) +R]
but the Function3 is just
trait Function3[-T1, -T2, -T3, +R]
#specialized is how Scala lets you avoid boxing on generics with primitives. But this comes at a price of compiler having to generate additional methods and classes, so beyond a certain threshold it will just produce a ridiculous amount of code (if not crash outright). So Function has, if my math is correct, 4 (specs on T1) x 6 (specs on R) = 24 copies of each specialized method and 24 extra classes in addition to just apply and a generic trait.
Oh, and by the way, those methods are postfixed with $mc and the JNI type signatures. So method ending in $mcDII is a specialized overload that returns a Double, and accepts two Ints as parameters. This is the type of function you're passing into tabulate inside transform, i.e. this part
(x, y) => f(a(x)(y))
While calls to f should show up with $mcDD postfix (returns a Double and accepts a Double).
However, calling
f(x, y, a(x)(y))
will become something like
unbox(f(box(x), box(y), box(a(x)(y))))
So I bothered you enough with the explanation. It's time for solution. To bring boxing of both methods to equivalent shape, create a specialized interface:
trait DoubleFunction3 {
def apply(a: Double, b: Double, c: Double): Double
}
and rewrite your signature in transformXY
def transformXY(f: DoubleFunction3): Container = //... same code
Since it's Scala 2.12 and you have just one abstract method in the trait, you can still pass lambdas, so this code:
t = t.transformXY { (x, y, h) =>
h + math.sqrt(x * x + y * y)
}
requires no change.
Now you might notice that this does not fully eliminate boxing because tabulate causes it too. This is definition of a single-dimensional tabulate:
def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = {
val b = newBuilder[T]
b.sizeHint(n)
var i = 0
while (i < n) {
b += f(i)
i += 1
}
b.result()
}
Note that it works with a generic Builder[T], calling a method +=(elem: T). Builder itself is not specialized, so it will do wasteful boxing/unboxing when creating your arrays. Your fix for this is to write a version that directly uses Double instead of T, for the dimensions you need.
I've created a:
newType Board = Board (Array (Int, Int) Life)
, where
data Life = Alive|Dead
Im trying to make a function to save the board to a String by pattern matching:
showBoard:: Config -> String
showBoard Board(array ((0, 0), (w, h)) [(a:as)]) = *code*
But this only gives me "Parse error in pattern: array". I cant see what's wrong?
You can only pattern-match on data constructors. array is not a data constructor; it is a regular function that internal uses the Array data constructor(s) to create and return an Array value. The internal details
of an Array are not exposed, preventing you from pattern-matching on them.
Instead, you need use the functions provided for looking at an Array value. These can be composed with a function that does take arguments you can pattern match on.
-- bounds :: Array i e -> (i, i)
-- elems :: Array i e -> [e]
showConfig :: Board -> String
showConfig (Board arr) = showConfig' (bounds arr) (elems arr)
where showConfig' :: ((Int,Int),(Int,Int)) -> [Life] -> String
showConfig' ((0,0),(w,h)) (a:as) = ...
If you modify your Board type to
newtype Board = Board { getArray :: Array (Int, Int) Life }
you can rewrite showConfig in an applicative style:
showConfig = (showConfig' <$> boards <*> elems) . getArray
where showConfig' ((0,0),(w,h)) (a:as) = ...
I would like to be able to use an array of functions along this line:
type SomeFunc =
| StringFunc of (int -> string)
| DecimalFunc of (int -> decimal)
let dataCols = Dict<string, SomeFunc>()
dataCols["A"] <- fun x -> sprintf "%d" x
dataCols["B"] <- fun x -> decimal x
// would want to have:
(dataCols["A"] 0) // "0"
(dataCols["B"] 0) // 0M
How could I express this idea in valid F# code?
The first thing is that you'll need to wrap the functions in StringFunc or DecimalFunc when putting them into the dictionary:
let dataCols = Dictionary<string, SomeFunc>()
dataCols["A"] <- StringFunc(fun x -> sprintf "%d" x)
dataCols["B"] <- DecimalFunc(fun x -> decimal x)
When you want to call the function, you'll need to handle the two cases separately. One issue here is that your two functions return different results. You cannot really do this directly, so when calling the function you'll have to return a boxed obj, or you'd have to define a new discriminated union that's either string or decimal. The first option looks like this:
let call func arg =
match func with
| StringFunc f -> box (f arg)
| DecimalFunc f -> box (f arg)
Then you can use the call helper:
call (dataCols["A"]) 0
call (dataCols["B"]) 0
The boxing means that you'll get back obj, but it's hard to say what would be the best way to handle this without knowing more about your specific situation.
From your code, I get the impression that the input type is always going to be the same (int in the example), in order to be able to call any column without knowing its type.
If so, you might want to use a DU for the return type, and not for the function type. This way you'll get the calling behaviour you want.
type ColumnValue =
| StringValue of string
| DecimalValue of decimal
let dataCols = Dictionary<string, (int -> ColumnValue)>()
dataCols.["A"] <- fun x -> StringValue (sprintf "%d" x)
dataCols.["B"] <- fun x -> DecimalValue (decimal x)
// what you get
dataCols.["A"] 0 // (StringValue "0")
match (dataCols.["A"] 0) with
| StringValue s -> printf "%s" s
| DecimalValue d -> printf "%M" d