function takes too many arguments F# - f#

I have the following code. I explicitly defined the return type as boolean
let inputChecker (romanNumber:list<char>) :bool = function
| [] -> false
| head::tail when head<= tail.Head && tail.Head<=tail.Tail.Head -> false
| _ -> true
but i think it consider the :bool as a parameter. I also tried (:bool), but still doesn't work.

If you use function, you don't specify the argument in the signature:
let inputChecker: (char list -> bool) = function
| [] -> false
| head::tail when head<= tail.Head && tail.Head<=tail.Tail.Head -> false
| _ -> true
If you want to specify the argument explicitly, use match
let inputChecker (romanNumber: char list): bool =
match romanNumber with
| [] -> false
| head::tail when head<= tail.Head && tail.Head<=tail.Tail.Head -> false
| _ -> true
Type annotations are not necessary, you can skip them.

Related

Use logical operator as combine closure in reduce

I am trying to reduce an array of Bools by applying the logical operator OR (||) using the following code, however I get an error:
func reduceBools(values: [Bool]) -> Bool {
return values.reduce(false, combine: ||)
}
Ambiguous reference to member '||'
Analogously for integers the code works like a charm.
func reduceInts(values: [Int]) -> Int {
return values.reduce(0, combine: +)
}
I was able to make it work by adding a || function (code below) or using a { $0 || $1 } closure but I dislike these approaches and I would prefer simply passing the operator.
func ||(lhs: Bool, rhs: Bool) -> Bool {
return lhs || rhs
}
The same thing happens for the logical AND (&&) operator.
How can I make it work without using the hack above?
As an alternative, you could use the following approach
// ||
func reduceBoolsOr(values: [Bool]) -> Bool {
return values.contains(true)
}
// &&
func reduceBoolsAnd(values: [Bool]) -> Bool {
return !values.contains(false)
}
Note that .reduce comes with an overhead. If the end result is the importance of your question (rather than enquiring above the unexpected behaviour of || and && operators in this context), then perhaps the pragmatic approach above can be of help, even if it doesn't really reduce the array, however producing the same result due to the simple nature of the boolean type.
Swift 4.2+ / Xcode 10.0+
In modern versions of Swift there is allSatisfy function, which checks all elements for satisfying some rule.
In OP's case:
values.allSatisfy { $0 }
UPD:
To make this work for OR, do
!values.allSatisfy{!$0}
Thanks to Andy Weinstein
Following approach will work
values.reduce(false) { $0 || $1 }
Ambiguous reference to member '||' means, that there are more than one possible candidates, from which compiler is not able to choose. In your case those are
public func ||<T : BooleanType, U : BooleanType>(lhs: T, #autoclosure rhs: () throws -> U) rethrows -> Bool
and
public func ||<T : BooleanType>(lhs: T, #autoclosure rhs: () throws -> Bool) rethrows -> Bool
probably your 'hack' using a { $0 || $1 } is the best solutions here.
This happens because of Swifts closure semantics. It takes your arguments and applies function to them, omitting argument names.
protocol Numeric {
...
public static func +(lhs: Self, rhs: Self) -> Self
...
}
In example with Ints, you would pass (Int, Int) into a closure, and + function in Numeric protocol expects exactly two ints to sum them.
Thats why code like below works just fine
[1, 2, 3, 4].reduce(0, +)
Because you just took 2 ints, and applied function, which takes just two ints.
If you write your own function, which would take just two argument, it would work as well.
func myOwnAwesomeFunc<T: Numeric>(a: T, b: T) -> T { in
return 1 // production ready
}
[1, 2, 3, 4].reduce(0, myOwnAwesomeFunc) // prints 1
Good so far. But why can't we write
[true, false, true].reduce(false, ||) // yields Cannot invoke 'reduce'
// with an argument list of type
// '(Bool, (Bool, #autoclosure () throws -> Bool) throws -> Bool)'
That's because this operator takes bool and a closure, which returns bool. Not bool, closure!
But if it is like this, why aren't we writing true || { false }() ?
Thats because of #autoclosure, which takes care of curly braces for us.
Main question, why is it implemented this way, so we can't use Swifts awesome short-hand closure syntax with booleans? Idk
Here's another approach, I modified the reduceBools function to take the operator as a parameter -
typealias LogicalOperator = ((Bool, #autoclosure () throws -> Bool) throws -> Bool)
func reduceBools(values: [Bool], combine: LogicalOperator) -> Bool {
var started: Bool = false
return values.reduce(into: true, { (result, value) in
result = started ? try! combine(result, value) : value // obviously up to you how you'd handle the try/catch
started = true
})
}
let bools = [true, false, false, true]
let result1 = self.reduceBools(values: bools, combine: ||)
print(result1) // prints true
let result2 = self.reduceBools(values: bools, combine: &&)
print(result2) // prints false
Or it could be more useful as an extension of Sequence -
extension Sequence where Element == Bool {
func reduce(_ combine: LogicalOperator) -> Bool {
var started: Bool = false
return self.reduce(into: true, { (result, value) in
result = started ? try! combine(result, value) : value
started = true
})
}
}
print(bools.reduce(||)) // prints true

Compiler error when using function composition: Cannot convert value of type `([Character]) -> String` to expected > argument type `_ -> _`

I am playing around with the custom operator >>> for function composition that is suggested here.
I have defined the following:
infix operator >>> { associativity left }
func >>> <A, B, C>(f: B -> C, g: A -> B) -> (A -> C) {
return { x in f(g(x)) }
}
func toChars(s: String) -> [Character] {
return s.characters.reduce([]) { (acc, c) in acc + [c] }
}
func myReverse(xs: [Character]) -> String {
if let (head, tail) = xs.decompose {
return String(myReverse(tail)) + String(head)
}
return ""
}
Now, when I want to put together those two functions like this:
func reverseString(s: String) -> String {
return myReverse >>> toChars
}
I am getting the compiler error:
Cannot convert value of type ([Character]) -> String to expected
argument type _ -> _.
According to my understanding this should work. >>> is defined to take two functions f : B -> C and g : A -> B. Looking at the structure of my usage, the following becomes clear:
g in this case is toChar : String -> [Character], so A is String and B is [Character]
f in this case is myReverse : [Character] -> String, so B is [Character] and C is String
This matches the type definitions form above, however I am still getting a compiler error. Does anyone know what I am doing wrong? Is there a syntax issue with the code?
Note, I am using an Array extension where the function decompose is defined like so:
var decompose : (head: Element, tail: [Element])? {
if count > 0 {
return (self[0], Array(self[1..<count]))
}
return nil
}
myReverse >>> toChars returns a closure of type String -> String,
you still have to call the closure with a string argument:
func reverseString(s: String) -> String {
return (myReverse >>> toChars)(s)
}
But what you probably want is:
let reverseString = myReverse >>> toChars
In both cases, reverseString has the type String -> String,
so you can call it as
print(reverseString("foo"))
// oof

Swift String overload behavior of '>'

I have a playground:
let astr = "A"
let bstr = "a"
astr > bstr
"A" > "a"
Output:
false for the first use of > and an error for the second one:
Playground execution failed: :69:5: error: ambiguous use of operator '>'
"A" > "a"
^
Foundation.>:1:6: note: found this candidate
func >(lhs: String, rhs: NSString) -> Bool
^
Foundation.>:1:6: note: found this candidate
func >(lhs: NSString, rhs: String) -> Bool
This is the drill down of the real problem I am having:
var team = ["Jane","Kate","George","Zulma"]
let sortedteam = team.sorted({ $0 > $1 })
This is giving me the same error.
You can try to use the global sorted function instead, which doesn't have this issue:
var team = ["Jane","Kate","George","Zulma"]
let sortedteam = sorted(team, { $0 > $1 })
Alternatively you could remove some of the conciseness of the closure, so the compiler knows what types it's comparing.
var team = ["Jane","Kate","George","Zulma"]
let sortedteam = team.sorted({ (s1: String, s2: String) in s1 > s2 })

transducers and swift porting javascript code to swift code

I am trying practice writing transducers in swift, but I cannot successfully translate this functional javascript code to swift.
http://phuu.net/2014/08/31/csp-and-transducers.html
function mapping(transform) {
return function (reduce) {
return function (result, input) {
return reduce(result, transform(input));
};
};
}
func mapping<T,U> ( transform:(T)-> T ) -> ( (U,T)-> ( (U,T)->U ) ) {
return { ( transducer:(U,T) ) -> ( (U,T)->U ) in
return { (initial:U,element:T) -> U in
var transformedElement = transform(element);
var mInitial = transducer(initial,transformedElement); // this line is the problem
return mInitial;
}
}
func addOne (a:Int) -> (Int) {
return a+1;
}
func concat (c:Array<Int>,element:Int) -> (Array<Int>) {
var collection = c;
collection.append(element);
return collection;
}
var example3 = [1,2,3].reduce([], concat( mapping ( addOne ) ) );
According to http://phuu.net/2014/08/31/csp-and-transducers.html
and http://blog.cognitect.com/blog/2014/8/6/transducers-are-coming,
a reducing function has the signature
whatever, input -> whatever
In Swift, this is a function (or closure) of the type
(U, T) -> U
(using the usual short names T, U for generic types).
A transducer is a function that takes one reducing function as an argument
and returns another reducing function
(whatever, input -> whatever) -> (whatever, input -> whatever)
The corresponding Swift type is
((U,T) -> U) -> (U,T) -> U
mapping() takes a transformation as an argument an returns a transducer,
so it must be defined as
func mapping<T,U> (transform:(T) -> T) -> ((U,T)->U) -> (U,T) -> U
(Also the parameter in the first inner function of mapping is better called
"reducer" instead of "transducer", because it is the argument of the return value.)
In your example,
concat : ([Int], Int) -> [Int]
is a reducing function and mapping(addOne) is a transducer, therefore
mapping(addOne)(concat) : ([Int], Int) -> [Int]
is another reducing function, so that
var example3 = [1,2,3].reduce([], mapping(addOne)(concat))
gives the result [2,3,4].
Complete sample code:
func mapping<T,U> (transform:(T) -> T) -> ((U,T)->U) -> (U,T) -> U {
return { (reducer:((U,T) -> U)) -> (U,T) -> U in
return { (initial:U, element:T) -> U in
return reducer(initial,transform(element))
}
}
}
func addOne (a:Int) -> (Int) {
return a+1;
}
// Slightly simplified and generalized:
func concat<T> (c:[T], element:T) -> [T] {
return c + [element];
}
var example3 = [1,2,3].reduce([], mapping (addOne)(concat))
println(example3) // [2, 3, 4]

How do I use function parameter as literal for pattern matching in F#?

How do I write a match function that takes two strings and compares them with each other? Right now I just have this. The first one does not work. Is there a better way?
let matchFn ([<Literal>]matchString) (aString : string) = match aString with
matchString -> true
| _ -> false
let matchFn (matchString : string) (aString : string) = match aString with
_ when (matchString = aString) -> true
| _ -> false
In this specific case, you could of course just write aString = matchString, but I suppose you are asking about the general case. Literals are allowed only on the module level, and they must have a simple constant expression on their right side (source).
However, you can use an active pattern for cases like this. For example (from here):
let (|Equals|_|) expected actual =
if actual = expected then Some() else None
and then use it like this:
let matchFn (matchString : string) (aString : string) =
match aString with
| Equals matchString -> true
| _ -> false
You can use a guarded match:
let matchFn matchString (aString : string) = match aString with
x when x = matchString -> true
| _ -> false
or, perhaps more idiomatically:
let matchFn (matchString:string) = function
| x when x = matchString -> true
| _ -> false

Resources