creating sequences in ML - sequence

datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq);
fun head(Cons(x,_)) = x | head Nil = raise EmptySeq;
fun tail(Cons(_,xf)) = xf() | tail Nil = raise EmptySeq;
datatype direction = Back | Forward;
datatype 'a bseq = bNil
| bCons of 'a * (direction -> 'a bseq);
fun bHead(bCons(x,_)) = x | bHead bNil = raise EmptySeq;
fun bForward(bCons(_,xf)) = xf(Forward) | bForward bNil = raise EmptySeq;
fun bBack(bCons(_,xf)) = xf(Back) | bBack bNil = raise EmptySeq;
so after all those definitions. here's what I'm trying to do. I need to take 2 sequences and make them into 1 sequence that I can move Farward and Back on.
for example if 1 sequence is 0123... and 2 is -1-2-3-4..., I get -4-3-2-10123.
my current location must always be the first element of the sequence going "up".
this is what I've tried to do:
(*************************************************************)
local
fun append_aux (Nil, yq) = yq
|append_aux (Cons(x,xf), yq) = Cons(x,fn() => append_aux(xf(),yq))
fun append(t,yq) = append_aux(Cons(t,fn() => Nil),yq)
in
fun seq2bseq (Cons(x,xrev)) (Cons(y,ynorm)) = bCons(y,fn Farward => seq2bseq (append(y,Cons(x,xrev))) (ynorm())
|Back => seq2bseq (xrev()) (append(x,Cons(y,ynorm))))
|seq2bseq (_) (_) = bNil
end;
but I get an error "match redundant" for the "Back" match and I can't figure out why.

Related

Conditionally change record in update

I would like to have some logic worked upon the Msg and, depending on the result, update the view in a different ways.
I'm flipping some cards, and I want to test two of the selected ones. Then, accept them as a pair or discard and try again.
update : Msg -> Model -> Model
update msg model =
case msg of
ClickedCard data ->
{ model
| activeCard = data.id
, (if List.lenght selectedCards < 2 then
selectedCards = data.id :: model.selectedCards
else if (List.take 1 model.selectedCards) == (List.drop 1 model.selectedCards) then
completedPairs = ( List.take 1 model.selectedCards , List.drop 1 model.selectedCards ):: model.completedPairs
else
selectedCards = List.drop 2 model.selectedCards)
}
_ ->
model
But, seems like I can't insert the logic there. Where should I put it, instead?
-- PROBLEM IN RECORD ------------------------------------------ src/Flipping.elm
I am partway through parsing a record, but I got stuck here:
126| { model
127| | activeCard = data.id
128| , (if List.lenght selectedCards < 2 then
^
I was expecting to see another record field defined next, so I am looking for a
name like userName or plantHeight.
The record update syntax doesn't work like that.
You can do the following.
update : Msg -> Model -> Model
update msg model =
case msg of
ClickedCard data ->
let
newModel = { model | activeCard = data.id }
in
if List.length selectedCards < 2 then
{newModel | selectedCards = data.id :: model.selectedCards}
else if (List.take 1 model.selectedCards) == (List.drop 1 model.selectedCards) then
{newModel | completedPairs = ( List.take 1 model.selectedCards , List.drop 1 model.selectedCards ):: model.completedPairs}
else
{newModel | selectedCards = List.drop 2 model.selectedCards)}
_ ->
model

Get constructor by value option in Elm (0.19.1)

I have some types:
type alias Type1 = { name : String }
type alias Type2 = { name : String, age : Int }
type S
= S1 Type1
| S2 Type2
So, when I want to build my info I can do the following:
a = S1 { name = "Name1" }
b = S2 { name = "Name2", age = 100 }
Now, I would like to get its constructor (S1 or S2) based on the info passed as parameter to the constructorByData function. Examples:
constructorByData a -- It should be returned `S1`
constructorByData b -- It should be returned `S2`
This is my aproach:
constructorByData : S -> (a -> S)
constructorByData s =
case s of
S1 _ -> S1
S2 _ -> S2
Please, note that the above code does not work. I get the following error:
-- TYPE MISMATCH ---------------------------------------------------------- REPL
Something is off with the 2nd branch of this `case` expression:
14| S2 _ -> S2
^^
This `S2` value is a:
Type2 -> S
But the type annotation on `constructorByData` says it should be:
a -> S
-- TYPE MISMATCH ---------------------------------------------------------- REPL
Something is off with the 1st branch of this `case` expression:
13| S1 _ -> S1
^^
This `S1` value is a:
Type1 -> S
But the type annotation on `constructorByData` says it should be:
a -> S
The main reason I want to do this is because I want to do the following by generalizing the message:
type Field
= Name
| Age
type Msg
= UpdateFieldString S Field String
| UpdateFieldInt S Field Int
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
UpdateFieldString s field value -> updateFieldString model s field value
UpdateFieldInt s field value -> updateFieldInt model s field value
And is for this I need the constructor in updateField{String, Int} functions

What is the most idiomatic way of representing errors in F#

I'm working on F# project and I wonder what is the best practice to return domain error using Result type in F#. There are several ways of doing it which I consider:
Inherited exceptions
type DomainException(message) =
inherit Exception(message)
type ItemNotFoundException(item) =
inherit DomainException(sprintf "Item %s is not found" item)
let findItem item =
match item with
| Some x -> Ok x
| None -> Error(new ItemNotFoundException("someitem"))
Custom record type
type DomainError =
{ Name : string
Message : string }
let findItem item =
match item with
| Some x -> Ok x
| None ->
Error({ Name = "ItemNotFound"
Message = "Item someitem is not found" })
Discriminated union of record type
type DomainErrorTypes =
| ItemNotFoundError of DomainError
| ItemInvalidFormat of DomainError
let findItem item =
match item with
| Some x -> Ok x
| None ->
{ Name = "ItemNotFound"
Message = "Item someitem is not found" }
|> ItemNotFoundError
|> Error
So which way is more idiomatic and convenient to use? I also will be happy to see better options.
Typically it would be a discriminated union. Every error requires different details to accompany the message. For instance:
type DomainErrorTypes =
| ItemNotFound of ItemId
| FileNotFound of string
| InvalidFormat of format
| IncompatibleItems of Item * Item
| SQLError of code:int * message:string
| ...
You can also capture some exceptions (not necessarily all):
| ...
| Exception of exn

What local-storage tooling does WebSharper provide?

In looking at the documentation for WebSharper's local storage, the SetItem item is string * string -> unit (and GetItem is string -> string).
This means that I'll need to convert anything I want to store into strings and do the reverse to retrieve them. Or, to put it in another way, I'll need to serialize and de-serialize them. Is there a way to use the behind-the-scenes conversion that WebSharper already does for RPC calls, or am I stuck with using a server-side library like FsPicker?
Not built in yet, I have been using this helper module to make local storage usable the same way as a ref cell:
open IntelliFactory.WebSharper
// Helper for handling localstorage, making a stored value work like a ref cell.
[<JavaScript; AutoOpen>]
module LocalStorage =
open IntelliFactory.WebSharper.Html5
let localStorage = Window.Self.LocalStorage
type IValue<'T> =
abstract Value: 'T with get, set
let [<Inline>] ( ! ) (x: IValue<_>) = x.Value
let [<Inline>] ( := ) (x: IValue<_>) v = x.Value <- v
// Redefining Ref to use IValue
type Ref<'T> (value: 'T) =
let mutable v = value
interface IValue<'T> with
member this.Value
with get() = v
and set value = v <- value
let [<Inline>] ref v = Ref v
let incr i = i := !i + 1
let decr i = i := !i - 1
type IStorageItem<'T> =
inherit IValue<'T>
abstract Save: unit -> unit
abstract Delete: unit -> unit
type JSONStorageItem<'T>(key, defaultVal) =
let mutable value = None
let getValue() =
match value with
| Some v -> v
| _ ->
let v =
match localStorage.GetItem key with
| null -> defaultVal
| s ->
Json.Parse s :?> _
value <- Some v
v
interface IStorageItem<'T> with
member this.Value
with get() = getValue()
and set v =
try localStorage.SetItem(key, Json.Stringify v)
value <- Some v
with _ -> JavaScript.Alert "Saving data to storage failed."
member this.Save() =
try localStorage.SetItem(key, Json.Stringify (getValue()))
with _ -> JavaScript.Alert "Saving data to storage failed."
member this.Delete() =
localStorage.RemoveItem key
value <- None
let [<Inline>] getJSONStorage key defaultVal = JSONStorageItem<_>(key, defaultVal) :> IStorageItem<_>
However this can currently only stringify/parse straight data objects: record, list, array, tuple and union types are ok, but no prototypes are restored.

Scala: Using HashMap with a default value

I have a mutable HashMap and would like to use it like a default-dictionary. The obvious method appears to be to use getOrElse and provide the default value each time as a second value. However this seems a little inelegant in my use case since the default value doesn't change.
var x = HashMap(1 -> "b", 2 -> "a", 3 -> "c")
println(x.getOrElse(4, "_")
println(x.getOrElse(5, "_"))
// And so on...
println(x.getOrElse(10, "_"))
Is there any way to create a HashMap (or similar class) such that attempting to access undefined keys returns a default value set on the creation of the HashMap? I notice that HashMap.default is just set to throw an exception but I wonder if this can be changed...
Wow, I happened to visit this thread exactly one year after I posted my last answer here. :-)
Scala 2.9.1. mutable.Map comes with a withDefaultValue method. REPL session:
scala> import collection.mutable
import collection.mutable
scala> mutable.Map[Int, String]().withDefaultValue("")
res18: scala.collection.mutable.Map[Int,String] = Map()
scala> res18(3)
res19: String = ""
Try this:
import collection.mutable.HashMap
val x = new HashMap[Int,String]() { override def default(key:Int) = "-" }
x += (1 -> "b", 2 -> "a", 3 -> "c")
Then:
scala> x(1)
res7: String = b
scala> x(2)
res8: String = a
scala> x(3)
res9: String = c
scala> x(4)
res10: String = -
scala> val x = HashMap(1 -> "b", 2 -> "a", 3 -> "c").withDefaultValue("-")
x: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,b), (2,a), (3,c))
scala> x(3)
res0: java.lang.String = c
scala> x(5)
res1: java.lang.String = -
EDIT:
For mutable.HashMap, you could do the following:
scala> import collection.mutable
import collection.mutable
scala> val x = new mutable.HashMap[Int, String] {
| override def apply(key: Int) = super.get(key) getOrElse "-"
| }
x: scala.collection.mutable.HashMap[Int,String] = Map()
scala> x += (1 -> "a", 2 -> "b", 3 -> "c")
res9: x.type = Map((2,b), (1,a), (3,c))
scala> x(2)
res10: String = b
scala> x(4)
res11: String = -
There might be a better way to do this. Wait for others to respond.
I'm more a java guy... but if getOrElse is not final, why don't you just extend HasMap and provide something like this:
override def getOrElse(k: Int, default: String) = {
return super.getOrElse(k,"_")
}
Note: syntax is probably screwed up but hopefully you'll get the point