Parse error on Guards (Haskell) - parsing

I have the following code
reconocerCliente :: Cliente -> Cliente -> Cliente
reconocerCliente cliente otroCliente
| verificarCliente cliente otroCliente = cliente {amigos = otroCliente : amigos}
| otherwise = id cliente
This are the used functions:
verificarCliente :: Cliente -> Cliente -> Bool
verificarCliente cliente otroCliente = (esElMismo cliente otroCliente) && not(any(== otroCliente) amigos)
esElMismo :: Cliente -> Cliente -> Bool
esElMismo (Uncliente nombre _ _ _) (Uncliente otroNombre _ _ _) = nombre /= otroNombre
Each time i compile i get "error: parse error on input ‘|’"
Exactly in this line:
| verificarCliente cliente otroCliente = cliente {amigos = otroCliente : amigos}
I dont know if my problem is with the indentation (Its done with spaces and not with Tabs) or my guards

The code you have pasted has no syntactical errors: it works fine when I paste it into a .hs file, with an appropriate definition for Cliente.
The one mistake that you do have wouldn't cause the error message you're getting:
cliente {amigos = otroCliente : amigos}
The second occurrence of amigos has the wrong type here: recall that amigos is a function defined by your record. It is not implicitly pattern-matched against cliente. Instead, you could write something like:
cliente {amigos = otroCliente : amigos cliente}

Related

How do access a value that belongs to a record from that record itself?

I am REALLY new to F#, so I might have used the wrong terminology here. Please feel free to correct me if I am wrong, I would really appreciate it! Anyways, on to the question
I have a record that I have defined as so:
type EventSource = {
SourceName: string
Address: string
ParseDocument: HtmlDocument -> Event seq }
And I have created an instance of that record like so:
let lofSource = {
SourceName = "LOF"
Address = "https://lof.dk/syd/kurser"
ParseDocument = fun document ->
document.Descendants ["div"]
|> Seq.filter (fun d -> d.HasClass("item"))
|> Seq.map (
fun e ->
let linkElement
= e.Descendants (fun j -> j.HasClass "item-title")
|> Seq.head
|> (fun y -> y.Descendants ["a"])
|> Seq.map (fun fa -> fa.Attribute "href")
|> Seq.head
{
Title = e.AttributeValue "data-holdnavn"
Link = linkElement.Value()
Status = e.AttributeValue "data-status"
Image = Address //Here!
City = e.AttributeValue "data-bynavn"
Date = System.DateTime.ParseExact(e.AttributeValue("data-datosort"), "yyyyMMdd", null);
PostalCode = e.AttributeValue("data-postnr")})
}
On the line where I am trying to assign a value the Image member, It tells me that the value or constructor 'Address' is not defined.
I have tried using a self-identifier on the instantiation of the record and then trying to access Address like
this.Address
but it tells me that 'this' is not defined. I am guessing I am missing something quite fundamental here, can anyone help me? Is what I am trying to do nonsensical?
You can't do this with records. See: Reference a record from within itself during construction
You can do it with another binding (I couldn't get your code to compile and have simplified it):
type EventSource = {
SourceName: string
Address: string
ParseDocument: string -> string}
let lofSource =
let helloThere = "General Kenobi"
{
SourceName = "LOF"
Address = foo
ParseDocument = fun document ->
foo
}

F# computation expression when is Combine called

I tried to implement this straight forward Maybe monad. So basically the whole expression evaluates to Nothing if one of the middle step is Nothing.
type Maybe<'a> =
| Just of 'a
| Nothing
type MaybeBuilder () =
member this.Combine ((first, second) : Maybe<'a> * Maybe<'b>) : Maybe<'b> =
printfn "Combine called"
match first with
| Nothing -> Nothing
| _ ->
match second with
| Nothing -> Nothing
| _ as a -> a
member this.Zero () = Just ()
member this.Bind((m, f) : Maybe<'a> * ('a -> Maybe<'b>)) =
printfn "Bind called"
match m with
| Nothing -> Nothing
| Just a -> f a
let MaybeMonad = MaybeBuilder()
let foobar =
MaybeMonad {
let! foo = Just "foo"
Just 1
Nothing
}
I expected foobar be translated into Just "foo" >>= fun foo -> Combine(Just 1, Nothing), however Combine wasn't called.
That's not the way the computation expression is expected to be written. Each time you want 'yield a result' you need to add some keyword (return, return!, yield or yield!) on the left side of the expression, in your example I would add a return!:
let foobar =
MaybeMonad {
let! foo = Just "foo"
return! Just 1
return! Nothing
}
But then you need to add its definition to the builder:
member this.ReturnFrom (expr) = expr
then the compiler will ask you to add a Delay method, in your case I think you're looking for something like:
member this.Delay(x) = x()
Almost there, now you have a value restriction, most likely because the Combine you defined doesn't use the same type on both arguments, you can either fix it or just add a type annotation in the return type:
let foobar : Maybe<int> =
MaybeMonad {
let! foo = Just "foo"
return! Just 1
return! Nothing
}
That's it, now you get:
Bind called
Combine called
printed and:
val foobar : Maybe<int> = Nothing
If you want to understand all the details of CEs have a look at this nice article: https://www.microsoft.com/en-us/research/publication/the-f-computation-expression-zoo/

Type unit does not have null as a proper value

Below I post a fragment of my F# program that causes problems.
...
match words with
| name :: "of" :: context :: "=" :: value :: _ when Double.TryParse(value) |> fst ->
let var = new FuzzyVariable(name, context, Double.Parse value)
fuzzyVars <- var :: fuzzyVars
In line:
fuzzyVars <- var :: fuzzyVars
I get "Type unit does not have null as a proper value" error. I am fairly new to F# programming and I don't quite know what might be causing this issue.
fuzzyVars is of type FuzzyVariable list. FuzzyVariable is a custom defined type.
EDIT.
As #Tomas Petricek pointed out there was a line in my code that returned null:
| [] -> null
My intention was to ignore value of the match. The proper way to do it is:
| [] -> ()
After that change everything works fine.
As already mentioned, the problem is not in the piece of code you posted - it looks like some other part of your program makes the F# compiler think that the expression fuzzyVars <- var :: fuzzyVars should have a type that admits null (but that's not the case, because it returns unit).
I was able to get the same error by writing:
open System
type FuzzyVariable(a:string, b:string, c:float) =
member x.A = ""
let mutable fuzzyVars : (FuzzyVariable list) = []
let words = [null; "of"; "context"; "="; "5"]
And the main part:
null = (match words with
| name :: "of" :: context :: "=" :: value :: _ when Double.TryParse(value) |> fst ->
let var = new FuzzyVariable(name, context, Double.Parse value)
fuzzyVars <- var :: fuzzyVars)
You probably do not have something like this in your code :-) but perhaps the error message might give you a pointer to where the null comes from. Here, I get:
error FS0001: The type 'unit' does not have 'null' as a proper value. See also C:\Users\Tomas\AppData\Local\Temp\~vs648E.fsx(8,0)-(8,4).
And the code on line 8 between character 0 and 4 is the null value! So perhaps check out whether the error message gives you some more information? Or try looking for null elsewhere in your code... (It might be also caused by some unexpected indentation.)
I tried this and it compiled just fine:
open System
type test = {Name:string}
let mutable fuzzyVars : (test list) = []
match [null; "of"; "context"; "="; "5"] with
| name :: "of" :: context :: "=" :: value :: _ when Double.TryParse(value) |> fst ->
let var = {Name=name}
fuzzyVars <- var :: fuzzyVars
| a -> a |> ignore
The problem isn't in this section of code.

Avoiding nested pattern matching (possibly with maybe monad)

How could nested pattern matching, such as the following example, be re-written so that None is specified only once? I think the Maybe monad solves this problem. Is there something similar in the F# core library? Or, is there an alternative approach?
match a with
| Some b ->
let c = b.SomeProperty
match c with
| Some d ->
let e = d.SomeProperty
//and so on...
| None -> ()
| None -> ()
you can solve this using built-in capabilities: Option.bind
type A =
member this.X : B option = Unchecked.defaultof<_>
and B =
member this.Y : С option = Unchecked.defaultof<_>
and С =
member this.Z : string option = Unchecked.defaultof<_>
let a : A = Unchecked.defaultof<_>
let v =
match
a.X
|> Option.bind (fun v -> v.Y)
|> Option.bind (fun v -> v.Z) with
| Some s -> s
| None -> "<none>"
Frankly, I doubt that introducing full-fledged 'maybe' implementation (via computation expressions) here can shorten the code.
EDIT: Dream mode - on
I think that version with Option.bind can be made smaller if F# has more lightweight syntax for the special case: lambda that refer to some member of its argument:
"123" |> fun s -> s.Length // current version
"123" |> #.Length // hypothetical syntax
This is how the sample can be rewritten in Nemerle that already has such capabilities:
using System;
using Nemerle.Utility; // for Accessor macro : generates property for given field
variant Option[T]
{
| Some {value : T}
| None
}
module OptionExtensions
{
public Bind[T, U](this o : Option[T], f : T -> Option[U]) : Option[U]
{
match(o)
{
| Option.Some(value) => f(value)
| Option.None => Option.None()
}
}
}
[Record] // Record macro: checks existing fields and creates constructor for its initialization
class A
{
[Accessor]
value : Option[A];
}
def print(_)
{
// shortened syntax for functions with body -> match over arguments
| Option.Some(_) => Console.WriteLine("value");
| Option.None => Console.WriteLine("none");
}
def x = A(Option.Some(A(Option.Some(A(Option.None())))));
print(x.Value.Bind(_.Value)); // "value"
print(x.Value.Bind(_.Value).Bind(_.Value)); // "none"
I like desco's answer; one should always favor built-in constructs. But FWIW, here's what a workflow version might look like (if I understand the problem correctly):
type CE () =
member this.Bind (v,f) =
match v with
| Some(x) -> f x
| None -> None
member this.Return v = v
type A (p:A option) =
member this.P
with get() = p
let f (aIn:A option) = CE () {
let! a = aIn
let! b = a.P
let! c = b.P
return c.P }
let x = f (Some(A(None)))
let y = f (Some(A(Some(A(Some(A(Some(A(None)))))))))
printfn "Your breakpoint here."
I don't suggest this, but you can also solve it with exception handling:
try
<code that just keeps dotting into option.Value with impunity>
with
| :? System.NullReferenceException -> "None"
I just wanted to point out the rough equivalence of exception-handling to the Maybe/Either monads or Option.bind. Typically prefer one of them to throwing and catching exceptions.
Using Option.maybe from FSharpx:
open FSharpx
type Pet = { Name: string; PreviousOwner: option<string> }
type Person = { Name: string; Pet: option<Pet> }
let pers = { Name = "Bob"; Pet = Some {Name = "Mr Burns"; PreviousOwner = Some "Susan"} }
Option.maybe {
let! pet = pers.Pet
let! prevOwner = pet.PreviousOwner
do printfn "%s was the previous owner of %s." prevOwner pet.Name
}
Output:
Susan was the previous owner of Mr Burns.
But, e.g. with this person instead there is just no output:
let pers = { Name = "Bob"; Pet = None }

f# pattern matching with types

I'm trying to recursively print out all an objects properties and sub-type properties etc. My object model is as follows...
type suggestedFooWidget = {
value: float ;
hasIncreasedSinceLastPeriod: bool ;
}
type firmIdentifier = {
firmId: int ;
firmName: string ;
}
type authorIdentifier = {
authorId: int ;
authorName: string ;
firm: firmIdentifier ;
}
type denormalizedSuggestedFooWidgets = {
id: int ;
ticker: string ;
direction: string ;
author: authorIdentifier ;
totalAbsoluteWidget: suggestedFooWidget ;
totalSectorWidget: suggestedFooWidget ;
totalExchangeWidget: suggestedFooWidget ;
todaysAbsoluteWidget: suggestedFooWidget ;
msdAbsoluteWidget: suggestedFooWidget ;
msdSectorWidget: suggestedFooWidget ;
msdExchangeWidget: suggestedFooWidget ;
}
And my recursion is based on the following pattern matching...
let rec printObj (o : obj) (sb : StringBuilder) (depth : int)
let props = o.GetType().GetProperties()
let enumer = props.GetEnumerator()
while enumer.MoveNext() do
let currObj = (enumer.Current : obj)
ignore <|
match currObj with
| :? string as s -> sb.Append(s.ToString())
| :? bool as c -> sb.Append(c.ToString())
| :? int as i -> sb.Append(i.ToString())
| :? float as i -> sb.Append(i.ToString())
| _ -> printObj currObj sb (depth + 1)
sb
In the debugger I see that currObj is of type string, int, float, etc but it always jumps to the defualt case at the bottom. Any idea why this is happening?
As others has pointed out, you need to invoke the GetValue member to get the value of the property - the iteration that you implemented iterates over PropertyInfo objects, which are "descriptors of the property" - not actual values. However, I don't quite understand why are you using GetEnumerator and while loop explicitly when the same thing can be written using for loop.
Also, you don't need to ignore the value returned by the sb.Append call - you can simply return it as the overall result (because it is the StringBuilder). This will actually make the code more efficient (because it enables tail-call optimizataion). As a last point, you don't need ToString in sb.Append(..), because the Append method is overloaded and works for all standard types.
So after a few simplification, you can get something like this (it's not really using the depth parameter, but I guess you want to use it for something later on):
let rec printObj (o : obj) (sb : StringBuilder) (depth : int) =
let props = o.GetType().GetProperties()
for propInfo in props do
let propValue = propInfo.GetValue(o, null)
match propValue with
| :? string as s -> sb.Append(s)
| :? bool as c -> sb.Append(c)
| :? int as i -> sb.Append(i)
| :? float as i -> sb.Append(i)
| _ -> printObj currObj sb (depth + 1)
Here is how I got it to work...
let getMethod = prop.GetGetMethod()
let value = getMethod.Invoke(o, Array.empty)
ignore <|
match value with
| :? float as f -> sb.Append(f.ToString() + ", ") |> ignore
...
In your example, enumer.Current is an object containing a PropertyInfo. This means that currObj is always a PropertyInfo object, and will always correspond to the last case in your match statement.
Since you're interested in the type of the value of the property, you'll need to call the GetValue() method of the PropertyInfo to get to the actual value of the property (as in ChaosPandion's answer).
Since an Enumerator returns its values as objects, you'll also need to cast the enum.current to a PropertyInfo before you can access GetValue.
Try replacing
let currObj = (enumer.Current : obj)
with
let currObj = unbox<PropertyInfo>(enumer.Current).GetValue (o, null)
With this change, I can get your code to work (in FSI):
> let test = {authorId = 42; authorName = "Adams"; firm = {firmId = 1; firmName = "GloboCorp inc."} };;
> string <| printObj test (new StringBuilder()) 1;;
val it : string = "42Adams1GloboCorp inc."
Are you sure the program is not behaving as expected? The debugger spans are not always reliable.
You want something like this instead.
let rec printObj (o : obj) (sb : StringBuilder) (depth : int)
let props = o.GetType().GetProperties() :> IEnumerable<PropertyInfo>
let enumer = props.GetEnumerator()
while enumer.MoveNext() do
let currObj = (enumer.Current.GetValue (o, null)) :> obj
ignore <|
match currObj with
| :? string as s -> sb.Append(s.ToString())
| :? bool as c -> sb.Append(c.ToString())
| :? int as i -> sb.Append(i.ToString())
| :? float as i -> sb.Append(i.ToString())
| _ -> printObj currObj sb (depth + 1)
sb
This is coming from the MSDN docs on the Array class:
In the .NET Framework version 2.0, the
Array class implements the
System.Collections.Generic.IList,
System.Collections.Generic.ICollection,
and
System.Collections.Generic.IEnumerable
generic interfaces. The
implementations are provided to arrays
at run time, and therefore are not
visible to the documentation build
tools. As a result, the generic
interfaces do not appear in the
declaration syntax for the Array
class, and there are no reference
topics for interface members that are
accessible only by casting an array to
the generic interface type (explicit
interface implementations). The key
thing to be aware of when you cast an
array to one of these interfaces is
that members which add, insert, or
remove elements throw
NotSupportedException.

Resources