Cannot assign a value of type '[CFString]' to a value of type '[String]' - xcode7

I just downloaded the new Xcode 7 beta 5 and I cannot find a way to resolve this error. It keeps highlighting the line "pickker.mediaTypes = [kUTTypeImage]" and says "Cannot assign a value of type '[CFString]' to a value of type '[String]'"
if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerControllerSourceType.Camera
picker.mediaTypes = [kUTTypeImage]
picker.allowsEditing = true
self.presentViewController(picker, animated: true, completion: nil)
}
else{
NSLog("No Camera.")
}

Try casting the CFString to a String like so:
picker.mediaTypes = [kUTTypeImage as String]

Related

No index signature with a parameter of type 'string' was found on type 'HTMLScriptElement'

I have an issue with the type of attributes of HTMLScriptElement.
In the below code, the issue come at line:
script[attribute.name] = attribute.value ? attribute.value : true
with the hint: "TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'HTMLScriptElement'.   No index signature with a parameter of type 'string' was found on type 'HTMLScriptElement'."
const generateFromSource = (codeString: string) => {
let script = document.createElement('script')
let template = document.createElement('div')
template.innerHTML = codeString
const element = template.getElementsByTagName('script')[0]
for (let attribute of element.attributes) {
if (attribute) {
script[attribute.name] = attribute.value ? attribute.value : true
}
}
document.head.appendChild(script)
}
Please help me with some suggestions. Thank you!
Indexing script local in order to get particular attribute hardly will work in JS: script.getAttribute(attributeName) will.
Setting particular script's attribute value might be done this way:
script.setAttribute(attribute.name, attribute.value);

F#: Apply a value as though it is a function

Is it possible in F# to apply a value as though it is a function? For example:
let record =
{|
Func = fun x -> x * x
Message = "hello"
|}
let message = record.Message // unsweetened field access
let unsweet = record.Func 3 // unsweetened function application
let sweet = record 3 // sweetened function application
Right now, the last line doesn't compile, of course:
error FS0003: This value is not a function and cannot be applied.
Is there some sort of syntactical sweetener that would allow me to "route" function application as I see fit, while still retaining its normal unsweetened behavior as well? I'm thinking of something magic like this:
// magically apply a record as though it was a function
let () record arg =
record.Func arg
(Note: I used a record in this example, but I'd be happy with a class as well.)
The closest thing I can think of would be a custom operator using statically resolved type parameters to resolve a specific property of type FSharpFunc, then invoke the function with the supplied input parameter. Something like this:
let record =
{|
Func = fun x -> x * x
Message = "hello"
|}
let inline (>.>) (r: ^a) v =
let f = (^a : (member Func: FSharpFunc< ^b, ^c>) r)
f v
record >.> 3 // val it : int = 9

why no intellisense csvprovider in msfs?

I'm experimenting with FsLab and CvsProvider. The script below works in the f# REPL, however, I do not get any intellisense of the column names of the ckv file e.g. "Date" and "Open" in example below. Therefore, the MSVS also marks those as undefined field, constructor, or member.
I install FsLab 1.1.6 with packet / nuget.
Any ideas how I can get it just like any tutorial video out there?
Regards, WP
#load "packages/FsLab/FsLab.fsx"
#load ".paket/load/net452/FSharp.Data.fsx"
open FSharp.Data
type Stocks = CsvProvider<"../../MSFT.csv">
//let msft = Stocks.Load("../../MSFT.csv")
let msft = CsvProvider<"../../MSFT.csv">.GetSample()
// Look at the most recent row. Note the 'Date' property
// is of type 'DateTime' and 'Open' has a type 'decimal'
let firstRow = msft.Rows |> Seq.head
let lastDate = firstRow.Date
let lastOpen = firstRow.Open
// Print the prices in the HLOC format
for row in msft.Rows do
printfn "HLOC: (%A, %A, %A, %A)" row.High row.Low row.Open row.Close

Pass Function to reduce duplicate code

I'm trying to learn F# and I feel like I can write / rewrite this block of code to be more "idiomatic" F# but I just can't figure out how I can accomplish it.
My simple program will be loading values from 2 csv files: A list of Skyrim potion effects, and a list of Skyrim Ingredients. An ingredient has 4 Effects. Once I have the Ingredients, I can write something to process them - right now, I just want to write the CSV load in a way that makes sense.
Code
Here are my types:
type Effect(name:string, id, description, base_cost, base_mag, base_dur, gold_value) =
member this.Name = name
member this.Id = id
member this.Description = description
member this.Base_Cost = base_cost
member this.Base_Mag = base_mag
member this.Base_Dur = base_dur
member this.GoldValue = gold_value
type Ingredient(name:string, id, primary, secondary, tertiary, quaternary, weight, value) =
member this.Name = name
member this.Id = id
member this.Primary = primary
member this.Secondary = secondary
member this.Tertiary = tertiary
member this.Quaternary = quaternary
member this.Weight = weight
member this.Value = value
Here is where I parse an individual comma-separated string, per type:
let convertEffectDataRow (csvLine:string) =
let cells = List.ofSeq(csvLine.Split(','))
match cells with
| name::id::effect::cost::mag::dur::value::_ ->
let effect = new Effect(name, id, effect, Decimal.Parse(cost), Int32.Parse(mag), Int32.Parse(dur), Int32.Parse(value))
Success effect
| _ -> Failure "Incorrect data format!"
let convertIngredientDataRow (csvLine:string) =
let cells = List.ofSeq(csvLine.Split(','))
match cells with
| name::id::primary::secondary::tertiary::quaternary::weight::value::_ ->
Success (new Ingredient(name, id, primary, secondary, tertiary, quaternary, Decimal.Parse(weight), Int32.Parse(value)))
| _ -> Failure "Incorrect data format!"
So I feel like I should be able to build a function that accepts one of these functions or chains them or something, so that I can recursively go through the lines in the CSV file and pass those lines to the correct function above. Here is what I've tried so far:
type csvTypeEnum = effect=1 | ingredient=2
let rec ProcessStuff lines (csvType:csvTypeEnum) =
match csvType, lines with
| csvTypeEnum.effect, [] -> []
| csvTypeEnum.effect, currentLine::remaining ->
let parsedLine = convertEffectDataRow2 currentLine
let parsedRest = ProcessStuff remaining csvType
parsedLine :: parsedRest
| csvTypeEnum.ingredient, [] -> []
| csvTypeEnum.ingredient, currentLine::remaining ->
let parsedLine = convertIngredientDataRow2 currentLine
let parsedRest = ProcessStuff remaining csvType
parsedLine :: parsedRest
| _, _ -> Failure "Error in pattern matching"
But this (predictably) has a compile error on second instance of recursion and the last pattern. Specifically, the second time parsedLine :: parsedRest shows up does not compile. This is because the function is attempting to both return an Effect and an Ingredient, which obviously won't do.
Now, I could just write 2 entirely different functions to handle the different CSVs, but that feels like extra duplication. This might be a harder problem than I'm giving it credit for, but it feels like this should be rather straightforward.
Sources
The CSV parsing code I took from chapter 4 of this book: https://www.manning.com/books/real-world-functional-programming
Since the line types aren't interleaved into the same file and they refer to different csv file formats, I would probably not go for a Discriminated Union and instead pass the processing function to the function that processes the file line by line.
In terms of doing things idiomatically, I would use a Record rather than a standard .NET class for this kind of simple data container. Records provide automatic equality and comparison implementations which are useful in F#.
You can define them like this:
type Effect = {
Name : string; Id: string; Description : string; BaseCost : decimal;
BaseMag : int; BaseDuration : int; GoldValue : int
}
type Ingredient= {
Name : string; Id: string; Primary: string; Secondary : string; Tertiary : string;
Quaternary : string; Weight : decimal; GoldValue : int
}
That requires a change to the conversion function, e.g.
let convertEffectDataRow (csvLine:string) =
let cells = List.ofSeq(csvLine.Split(','))
match cells with
| name::id::effect::cost::mag::dur::value::_ ->
Success {Name = name; Id = id; Description = effect; BaseCost = Decimal.Parse(cost);
BaseMag = Int32.Parse(mag); BaseDuration = Int32.Parse(dur); GoldValue = Int32.Parse(value)}
| _ -> Failure "Incorrect data format!"
Hopefully it's obvious how to do the other one.
Finally, cast aside the enum and simply replace it with the appropriate line function (I've also swapped the order of the arguments).
let rec processStuff f lines =
match lines with
|[] -> []
|current::remaining -> f current :: processStuff f remaining
The argument f is just a function that is applied to each string line. Suitable f values are the functions we created above, e.g.convertEffectDataRow. So you can simply call processStuff convertEffectDataRow to process an effect file and processStuff convertIngredientDataRow to process and ingredients file.
However, now we've simplified the processStuff function, we can see it has type: f:('a -> 'b) -> lines:'a list -> 'b list. This is the same as the built-in List.map function so we can actually remove this custom function entirely and just use List.map.
let processEffectLines lines = List.map convertEffectDataRow lines
let processIngredientLines lines = List.map convertIngredientDataRow lines
(optional) Convert Effect and Ingredient to records, as s952163 suggested.
Think carefully about the return types of your functions. ProcessStuff returns a list from one case, but a single item (Failure) from the other case. Thus compilation error.
You haven't shown what Success and Failure definitions are. Instead of generic success, you could define the result as
type Result =
| Effect of Effect
| Ingredient of Ingredient
| Failure of string
And then the following code compiles correctly:
let convertEffectDataRow (csvLine:string) =
let cells = List.ofSeq(csvLine.Split(','))
match cells with
| name::id::effect::cost::mag::dur::value::_ ->
let effect = new Effect(name, id, effect, Decimal.Parse(cost), Int32.Parse(mag), Int32.Parse(dur), Int32.Parse(value))
Effect effect
| _ -> Failure "Incorrect data format!"
let convertIngredientDataRow (csvLine:string) =
let cells = List.ofSeq(csvLine.Split(','))
match cells with
| name::id::primary::secondary::tertiary::quaternary::weight::value::_ ->
Ingredient (new Ingredient(name, id, primary, secondary, tertiary, quaternary, Decimal.Parse(weight), Int32.Parse(value)))
| _ -> Failure "Incorrect data format!"
type csvTypeEnum = effect=1 | ingredient=2
let rec ProcessStuff lines (csvType:csvTypeEnum) =
match csvType, lines with
| csvTypeEnum.effect, [] -> []
| csvTypeEnum.effect, currentLine::remaining ->
let parsedLine = convertEffectDataRow currentLine
let parsedRest = ProcessStuff remaining csvType
parsedLine :: parsedRest
| csvTypeEnum.ingredient, [] -> []
| csvTypeEnum.ingredient, currentLine::remaining ->
let parsedLine = convertIngredientDataRow currentLine
let parsedRest = ProcessStuff remaining csvType
parsedLine :: parsedRest
| _, _ -> [Failure "Error in pattern matching"]
csvTypeEnum type looks fishy, but I'm not sure what you were trying to achieve, so just fixed the compilation errors.
Now you can refactor your code to reduce duplication by passing functions as parameters when needed. But always start with types!
You can certainly pass a function to another function and use a DU as a return type, for example:
type CsvWrapper =
| CsvA of string
| CsvB of int
let csvAfunc x =
CsvA x
let csvBfunc x =
CsvB x
let csvTopFun x =
x
csvTopFun csvBfunc 5
csvTopFun csvAfunc "x"
As for the type definitions, you can just use records, will save you some typing:
type Effect = {
name:string
id: int
description: string
}
let eff = {name="X";id=9;description="blah"}

F# Beginner: retrieving an array of data from a server

I'm trying to grab data from a MySQL database.
Approach 2 - apply/map style
I'm using the MySQL ADO Reference to try to build this system. In particular, the example found at 21.2.3.1.7.
(using a pseudo code)
let table = build_sequence(query.read)
Where query.read returns a row in the table(Or rather, a list of elements that happen to be a row in the table). And the table variable is a list of lists that will represent a table returned from the query.
I've stared at the code given below, and it's syntax is over my head, I'm afraid.
Approach 1 - looping.
Problem 1: It's inelegant, requiring a mutable.
Problem 2: This just feels wrong, based on my prior experience with Prolog & Lisp. There's gotta be a more...functional way to do this.
I'm not sure where to begin though. Comments & thoughts?
let reader : MySql.Data.MySqlClient.MySqlDataReader = command.ExecuteReader()
let arr = []
let mutable rowIter = 0
let readingLoop() =
while(reader.Read()) do
rowIter = rowIter + 1
for i = 0 to reader.FieldCount do
//set arr[someiterator, i] = reader.GetValue[i].ToString())
The Seq type has a neat function for handling database cursors called generate_using (see F# Manual and the Data Access chapter in Foundations of F#). This is a higher order function that takes one function to open the cursor and another (called repeatedly) to process records from the cursor. Here is some code that uses generate_using to execute a sql query:
let openConnection (connectionName : string) =
let connectionSetting = ConfigurationManager.ConnectionStrings.Item(connectionName)
let connectionString = connectionSetting.ConnectionString
let connection = new OracleConnection(connectionString)
connection.Open()
connection
let generator<'a> (reader : IDataReader) =
if reader.Read() then
let t = typeof<'a>
let props = t.GetProperties()
let types = props
|> Seq.map (fun x -> x.PropertyType)
|> Seq.to_array
let cstr = t.GetConstructor(types)
let values = Array.create reader.FieldCount (new obj())
reader.GetValues(values) |> ignore
let values = values
|> Array.map (fun x -> match x with | :? DBNull -> null | _ -> x)
Some (cstr.Invoke(values) :?> 'a)
else
None
let executeSqlReader<'a> (connectionName : string) (sql : string) : 'a list =
let connection = openConnection connectionName
let opener() =
let command = connection.CreateCommand(CommandText = sql, CommandType = CommandType.Text)
command.ExecuteReader()
let result = Seq.to_list(Seq.generate_using opener generator)
connection.Close()
connection.Dispose()
result
For example to list all the tables in an Oracle database we need to define a column definition type and invoke executeSqlReader as follows:
type ColumnDefinition = {
TableName : string;
ColumnName : string;
DataType : string;
DataLength : decimal;
}
let tableList = executeSqlReader<ColumnDefinition>
"MyDatabase"
"SELECT t.table_name, column_name, data_type, data_length FROM USER_TABLES t, USER_TAB_COLUMNS c where t.TABLE_NAME = c.table_name order by t.table_name, c.COLUMN_NAME"
It can be hard to work with imperative APIs in a non-imperative way. I don't have MySql handy, but I made an approxmiation, hopefully this will provide inspiration. Seq.unfold is a function people find pretty awesome once they grok it. List.init (or Array.init) are also handy for initializing known-size data structures without using mutables.
#light
type ThingLikeSqlReader() =
let mutable rowNum = 0
member this.Read() =
if rowNum > 3 then
false
else
rowNum <- rowNum + 1
true
member this.FieldCount = 5
member this.GetValue(i) = i + 1
let reader = new ThingLikeSqlReader()
let data = reader |> Seq.unfold (fun (reader : ThingLikeSqlReader) ->
if reader.Read() then
Some (List.init reader.FieldCount (fun i -> reader.GetValue(i)), reader)
else
None) |> Seq.to_list
printfn "%A" data