I have no clue how to convert a Maybe value to a normal value ...
I have these lines...
pickChord : Model -> Note -> Chord
pickChord model note =
let
nextChord = List.head (List.filter (testChord note) model.possibleMajorChords)
in
nextChord
The compiler complains:
The definition of pickChord does not match its type annotation. - The type annotation for pickChord says it always returns:
Chord
But the returned value (shown above) is a:
Maybe Chord
How could I handle this problem?
Thanks.
This is why I love Elm. In it's own way, Elm is telling you you've got a design flaw.
Let's take a closer look. Here's the code as-is:
pickChord : Model -> Note -> Chord
pickChord model note =
let
nextChord = List.head (List.filter (testChord note) model.possibleMajorChords)
in
nextChord
So you've got a list of major chords which you then filter for a specific note. That produces a List of chords. However, the List type can represent an empty list, which is why List.head returns a Maybe. In your case, List.head can return either a Nothing or Just Chord.
Now, you can work around this with default values and error handling, but those are just work-arounds which dodge the real problem: The List type doesn't accurately fit your problem domain.
If you've got a list of all the major chords, I can't think of a reason why you would ever end up with an empty list after applying the filter. The filter should always find at least one chord. Assuming that's the case, what you need is a List-like type which can represent a list which is never empty; Which means head would always return a Chord and not a Maybe Chord. That would be a much better representation of what you're trying to achieve. Luckly, there's already such a type (which I didn't create but I use extensively) called List.Nonempty. Here's how it would work:
import List.Nonempty as NE
pickChord : Model -> Note -> Chord
pickChord model note =
NE.head (NE.filter (testChord note) model.possibleMajorChords)
Your model.possibleMajorChords would have to change from a List Chord to a List.Nonempty Chord, but it makes the whole maybe problem go away. That is of course assuming that my claim about the filter always returning at least one chord holds true.
Here's a link to the Nonempty package: http://package.elm-lang.org/packages/mgold/elm-nonempty-list/latest
If you have a list of Maybe cords you want to unwrap it then:
pickChord : Model -> Note -> Chord
pickChord model note =
let
nextChord = List.head (List.filter (testChord note) model.possibleMajorChords)
in
case nextChord of
Nothing ->
//some error here if you want
Just cord ->
cord
Because List.head won't give you an element in case of an empty list, you'll either have to provide a default value
pickChord : Model -> Note -> Chord
pickChord model note =
withDefault <chord> (List.head (List.filter (testChord note) model.possibleMajorChords))
Or leave the default Chord to the caller.
pickChord : Model -> Note -> Maybe Chord
pickChord model note =
List.head (List.filter (testChord note) model.possibleMajorChords)
Related
I found the following code in the Kotlin forum and it works fine.
sealed class JsonValue<out T>(val value: T) {
class JsonString(value: String) : JsonValue<String>(value)
class JsonBoolean(value: Boolean) : JsonValue<Boolean>(value)
class JsonNumber(value: Number) : JsonValue<Number>(value)
object JsonNull : JsonValue<Nothing?>(null)
class JsonArray<V>(value: Array<V>) : JsonValue<Array<V>>(value)
class JsonObject(value: Map<String, Any?>) : JsonValue<Map<String, Any?>>(value)
override fun toString(): String = value.toString()
}
fun main() {
var pi: JsonValue<Any?>
pi = JsonValue.JsonString("pi"); println (pi)
pi = JsonValue.JsonNumber(3.14); println (pi)
pi = JsonValue.JsonNull; println (pi)
}
But I do not understand why it uses out T.
An answer to a question about out in general states:
out T [...] means functions can return T but they can't take T as arguments.
in T [...] means functions can take T as arguments but they can't return T.
If I take a look at the above code, I can see many constructors (functions), which take T (the value) as an argument. And I see no function which returns T. So my inital impression was: this must be a typo, it should be in T. But it does not even compile with in T.
Why is it necessary to use out T, although the type goes into the constructor?
The constructor doesn't really count :) Only instance members matter - things that you can do to instances of JsonValue.
As explained in the linked answer, the whole idea of (declaration-site) covariance is that you are allowed to implicitly convert an instance of e.g. JsonValue<String> to JsonValue<Any?> if the type JsonValue<T> satisfies some requirements. One of the requirements is that JsonValue<T> should not have any functions that take in any Ts*, because if it did, weird things like this would happen:
val x: JsonValue<Any?> = JsonString("foo")
x.giveMeSomeT(123)
x at runtime holds an instance of JsonString, but the giveMeSomeT method in JsonString would expect a String, not an Int, but as far as the compiler is concerned, x is a JsonValue<Any?>, so this should compile, and bad things would happen at runtime.
So this is why having a function that takes in Ts stops you from marking JsonValue as out T. However, having a constructor that takes in a T is not problematic at all, since situations like the above cannot happen with just a constructor.
And I see no function which returns T
In fact, the getter of value returns T. Also note that you do not need something that returns T to in order to say out T. You just need to to have nothing that takes in Ts. This is vacuously valid for example:
class Foo<out T>
* More accurately and generally, whenever I say "take in any Ts", it should be "have T in an 'in' position", and whenever I say "return a T", it should be "have T in an 'out' position". This is to account for Ts being used as the type argument of other generic types.
The zip that accepts iterable is turning my object to Object[] vs the merge. After the zip, I cannot perform other transformation because I lost my object type. Is this the same concept as the stream's reduce combiner? Just wondering how to properly use it. Thanks.
final List<Object[]> list = Flux
.zip(List.of(Mono.just("hello"), Mono.just("world")), objects -> objects)
.collectList().block();
final List<String> strings = Flux
.merge(List.of(Mono.just("hello"), Mono.just("world")))
.collectList().block();
It's an API limitation at present since the generic type of the Iterable's Publisher isn't captured, so that type information isn't available to you in the method. This means you'll unfortunately have to do something unsafe if you want to keep the type information here.
The most trivial change to your current code to get a List<String[]> would be the following:
final List<String[]> list = Flux
.zip(List.of(Mono.just("hello"), Mono.just("world")), objects -> Arrays.stream(objects).toArray(String[]::new))
.collectList().block();
...but of course, you do lose your type safety.
Depending on your use case (generally speaking, if you combinator can combine elements one at a time rather than all in one go), you may also be able to use Flux.zip() in a reducer:
List<Flux<String>> l = new ArrayList<>();
l.add(Flux.just("hello", "me"));
l.add(Flux.just("world", "hungry"));
final List<String> strings = Flux.fromIterable(l)
.reduce((a, b) -> Flux.zip(a, b, (x, y) -> x + ", " + y))
.flatMap(x -> x.collectList())
.block();
It's not equivalent, but may be a type-safe alternative depending on what you need.
Looks like the first argument to the zip function takes a Iterable<? extends Publisher<?>> the question marks mean it can take whatever object.
and its second argument Function<? super Object[],? extends O> is a function that the first argument is "something" that is an object in an array, and the second argument is "something" that extends a concrete type.
So sadly you will be getting a Object[] it's how it is written. You can cast your objects to the correct.
I have never used it before but i played around with it a bit.
final Flux<String> helloWorldString = Flux.zip(List.of(Mono.just("hello"), Mono.just(" "), Mono.just("world")), objects -> {
StringBuilder value = new StringBuilder();
for (var object : objects) {
value.append((String) object);
}
return value.toString();
});
As it is a combinator i think its purpose is to take any objects[] and build a concrete type out if it.
Inspired by this question, I want to ask about how to handle input data type error in Rust. For example, the following function require input data type to be enum Animal. How about the user actually give an input with not-defined data type or even a empty one.
Should I add a None => None or _ => None in the match?
use std::fmt;
use std::io::prelude::*;
pub enum Animal {
Cat(String),
Dog,
}
impl fmt::Display for Animal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Animal::Cat(ref c) => f.write_str("c"),
Animal::Dog => f.write_str("d"),
}
}
}
fn main() {
let p: Animal = Animal::Cat("whiskers".to_owned()); // yes, work!
let p: Animal = Animal::BadCat("whiskers".to_owned()); // Badcat not defined,??
}
Compiler error:
error: no associated item named `BadCat` found for type `Animal` in the current scope
--> <anon>:20:25
|
20 | let p: Animal = Animal::BadCat("whiskers".to_owned()); // Badcat not defined,??
| ^^^^^^^^^^^^^^
Rust is a strongly1, statically typed, compile-time type checked language.
This means that unlike, say, Python, it is impossible for a user to pass an invalid type to your function (unless they're passing data that has been invalidly coerced via unsafe, but you can't reasonably detect this. See my post about incorrect transmutations to bool). You do not need to worry about this.
In the more general case, the only time you need to worry about type variant checking in Rust is when receiving data from outside Rust, e.g. through a configuration or data file, or else an FFI function. In these cases, it's customary to return a Result<Animal,ErrorMessage> of some sort to indicate bad data. However, in some cases, especially in FFI, if you receive data that's particularly malformed it may be acceptable to panic!.
This type of checking usually does not involve match statements on an enum, but rather more fundamental checks such as assertions about string or integer comparisons being one of a set of known values that you're trying to reinterpret to a higher level enum type.
1 There's some inconsistency and disagreement on what "strongly typed" actually means, in this case I'm using it to mean "few if any implicit type coercions".
I want to implement a callback in a swift project just like I used to do in Objective-C
I need a variable of type closure. That closure should take as a parameter an object and return nothing.
var downloadCompleted: (MLBook) -> (Void)!
When I need to trigger the callback I do this:
if self.downloadCompleted {
self.downloadCompleted(book)
}
The compiler complains with this error message:
Type '(MLBook) -> (Void)!' does not conform to protocol 'BooleanType'
If I remove the if statement the compiler says:
Property 'self.downloadCompleted' not initialized
even though it's implicitly unwrapped.
When I try to get the callback:
BookStore.sharedInstance.downloadCompleted{(book: MLBook) -> () in
println("Print if you got the callback")
}
I get this error message:
'(MLBook) -> ()' is not convertible to 'MLBook'
I'm more worried about the last error message as I'm not quite sure what it is trying to tell me.
Any help would be appreciated. Thanks
Here is your working example. You have a number of mistakes which the attached illustrates. Note
I had the download() method return Bool so that the result can be see in this screen shot.
But, your use of an implicitly unwrapped optional (aka '!') is incorrect. Such an optional is used when the value may be nil but will be assigned at a known time and not changed (see Apple documentation for a description). Your downloadCompleted is a true optional (at least in your example use). Thus, better code, which turns out to be slightly simpler is:
2 mistakes. 1st, The whole type should be wrapped in (), then followed a ? or ! as a optional or implicit unwrapped optional. 2nd, you should check with nil, in swift, no implicit boolean conversion.
In your use case, you should use Optional instead of Implicit unwrapped. Because there is big chance that your property has a nil value. With IUO(Implicit unwrapped optional), you skip compiler warning and will get a runtime error.
import Foundation
class MLBook {
var name = "name"
}
class A {
var downloadCompleted: ((MLBook) -> Void)?
func down(){
var book = MLBook()
if let cb = self.downloadCompleted {
cb(book)
}
}
}
var a = A()
a.downloadCompleted = {
(book: MLBook) -> Void in
println(book.name)
}
a.down()
I am currently implementing a Spec framework in F# and I want to hide the Equals, GetHashCode etc. methods on my should type, so that the API is not cluttered with these.
I know in C# it is done by making the class implement an interface like this:
using System;
using System.ComponentModel;
public interface IFluentInterface
{
[EditorBrowsable(EditorBrowsableState.Never)]
bool Equals(object other);
[EditorBrowsable(EditorBrowsableState.Never)]
string ToString();
[EditorBrowsable(EditorBrowsableState.Never)]
int GetHashCode();
[EditorBrowsable(EditorBrowsableState.Never)]
Type GetType();
}
I tried doing the same in F#:
type IFluentInterface = interface
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract Equals : (obj) -> bool
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract ToString: unit -> string
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract GetHashCode: unit -> int
[<EditorBrowsable(EditorBrowsableState.Never)>]
abstract GetType : unit -> Type
end
Implemented it in my type:
interface IFluentInterface with
member x.Equals(other) = x.Equals(other)
member x.ToString() = x.ToString()
member x.GetHashCode() = x.GetHashCode()
member x.GetType() = x.GetType()
but without success.
I also tried to override the methods in my type and adding the attribute that way, but that didn't do the trick either.
So the question remains, how can I clean up my API ?
Edit:
Thanks to the help (see below) I was able to solve my problem.
In summary, .Equals and .GetHashCode can be hidden via [<NoEquality>] [<NoComparison>] but that will also change the semantics.
The hiding via EditorBrowsable attributes does not work.
The only way to have a clean API and still be able to overload methods is to make these method members static.
The resulting class can be found by browsing inside my project FSharpSpec.
The type in question can be found here.
Thanks to everyone who helped me solve this problem.
Cheers ...
Alternatively, you could design the library using an alternative style using functions enclosed in a module. This is the usual way for writing functional code in F# and then you won't need to hide any standard .NET methods. To complete the example given by 'kvb', here is an example of object-oriented solution:
type MyNum(n:int) =
member x.Add(m) = MyNum(n+m)
member x.Mul(m) = MyNum(n*m)
let n = new MyNum(1)
n.Add(2).Mul(10) // 'ToString' shows in the IntelliSense
The functional way of writing the code might look like this:
type Num = Num of int
module MyNum =
let create n = Num n
let add m (Num n) = Num (m + n)
let mul m (Num n) = Num (m * n)
MyNum.create 1 |> MyNum.add 2 |> MyNum.mul 10
If you type MyNum., the F# IntelliSense will show the functions defined in the module, so you won't see any noise in this case.
Repeating my answer from
http://cs.hubfs.net/forums/thread/13317.aspx
In F# you can disallow Equals & GetHashCode (and remove them from intellisense) by annotating the type with the NoEquality and NoComparison attributes, as shown below. User-defined methods can also be hidden from the intellisense list via the Obsolete attribute or the CompilerMessage attribute with IsHidden=true. There is no way to hide the System.Object methods GetType and ToString from the F# intellisense.
[<NoEquality; NoComparison>]
type Foo() =
member x.Bar() = ()
member x.Qux() = ()
[<System.Obsolete>]
member x.HideMe() = ()
[<CompilerMessage("A warning message",99999,IsError=false,IsHidden=true)>]
member x.WarnMe() = ()
let foo = new Foo()
foo. // see intellisense here
I don't think that there is any way to do that in F# in general. In the particular case of .Equals and .GetHashCode, you can make them unusable by putting a [<NoEquality>] attribute on your type, but this actually has a semantic effect in addition to hiding those methods.
EDIT
It might also be worth mentioning that fluent interfaces are rarely used in F#, since it's much more idiomatic to use combinators and pipelining instead. For instance, imagine that we want to create a way to create arithmetic expressions. Rather than
let x = Expressions.MakeExpr(1).Add(2).Mul(3).Add(4)
I think that most F# users would prefer to write
open Expressions
let x =
1
|> makeExpr
|> add 2
|> mul 3
|> add 4
With this style, there's no need to hide members because expressions get piped to combinators, rather than calling methods of an expression builder.