What to do about 'discard' in Purescript do-notation? - purescript

Having a problem with some of the examples in the Learn Purescript by Example book. Specifically this code from section 9.3:
main :: Eff (canvas :: CANVAS) Unit
main = void $ unsafePartial do
Just canvas <- getCanvasElementById "canvas"
ctx <- getContext2D canvas
setFillStyle "#0000FF" ctx -- this's line 16 referred to in the error message
fillPath ctx $ rect ctx
{ x: 250.0
, y: 250.0
, w: 100.0
, h: 100.0
}
gives the following error:
in module Example.Rectangle
at src\Example\Rectangle.purs line 16, column 3 - line 16, column 29
A result of type
Context2D
was implicitly discarded in a do notation block.
You can use _ <- ... to explicitly discard the result.
while applying a function discard
of type Discard t0 => Bind t1 => t1 t0 -> (t0 -> t1 t2) -> t1 t2
to argument (setFillStyle "#0000FF") ctx
while inferring the type of discard ((setFillStyle "#0000FF") ctx)
in value declaration main
where t0 is an unknown type
t2 is an unknown type
t1 is an unknown type
See https://github.com/purescript/documentation/blob/master/errors/NoInstanceFound.md for more information,
The suggested error doesn't help and I can't work out what "discard" acctualy does. I also noticed a similar problem with, for example, the "simulate" function from section 8.17. If I try the suggestion of assigning using "_ <- " more random seeming errors crop up.
(This is using PSCi 0.11.5)

It is no more allowed to implicitly discard a value in a do block.
You can:
- ignore the value explicitly: _ <- setFillStyle....
- or if the return value is Unit (e.g. Eff fx Unit) you can simply import "discard" from "Prelude"

Related

Get a newtype'd records underlying type in purescript

I'm trying to see if there's an easy way to get the type of a newtype'd record to put in function signatures.
newtype T1 = T1 { foo:: Int}
derive instance newtypeT1 :: Newtype T1 _
... other classes that require me to newtype the record ...
I know I can access a records members with
_.property and I can compose that with unwrap
unwrap >>> _.property to get a function for that property, but I'd like to write a function similar to
testFoo :: forall a. (_ -> a) -> Effect a
testFoo accessor = (unwrap >>> accessor) <$> loadT1
This works but the wildcard symbol gives an warning, but I'm not sure how to get that record definition from T1. (This is a minimal example, I have a massive property object that is from an external source.
A workaround I've been using for now has been to declare my type like
type InnerT1 = { foo ::Int}
newtype T1 = T1 InnerT1
and exporting that InnerT1 so it can be used in my test file, but this seems a bit clunky and I am wondering if there is a better way?
You can use the Newtype class to get at the inner type:
testFoo :: forall a inner. Newtype T1 inner => (inner -> a) -> Effect a
testFoo accessor = (unwrap >>> accessor) <$> loadT1
This works without additional annotations, because the class has a functional dependency Newtype a b | a -> b, which means that the inner type is uniquely determined by the outer type.

How to use instance chain to solve overlapping

I've been trying next purescript ver 0.12.0-rc1.
I have a question how to use new feature 'instance chain'.
in my understanding the instance chain provides a feature to be able to specify instance resolving order explicitly. this solves avoid instance definition overlapping.
so I suppose it may work:
class A a
class B b
class C c where
c :: c -> String
instance ca :: A a => C a where
c = const "ca"
else
instance cb :: B b => C b where
c = const "cb"
data X = X
instance bx :: B X
main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = logShow $ c X
but cannot compiled.
what is not correctly?
or what is the instance chain usage?
result:
Error found:
in module Main
at src/Main.purs line 23, column 8 - line 23, column 20
No type class instance was found for
Main.A X
while applying a function c
of type C t0 => t0 -> String
to argument X
while inferring the type of c X
in value declaration main
where t0 is an unknown type
Even with instance chains matching is still done on the head of an instance. There is no "backtracking" when any of constraint fails for the chosen instance.
Your instances are completely overlapping on the head, so your first instance always matches before second one and it fails because there is no A instance for X.
Instance chains allows you to define explicit ordering of instance resolution without relying on for example alphabetical ordering of names etc. (as it was done till 0.12.0 version - please check the third paragraph here). For example you can define this overlapping scenario:
class IsRecord a where
isRecord :: a -> Boolean
instance a_isRecordRecord :: IsRecord (Record a) where
isRecord _ = true
instance b_isRecordOther :: IsRecord a where
isRecord _ = false
as
instance isRecordRecord :: IsRecord (Record a) where
isRecord _ = true
else instance isRecordOther :: IsRecord a where
isRecord _ = false
I hope it compiles - I don't have purs-0.12.0-rc yet ;-)

infinite type inferred due to pattern variable

Using a pattern variable that names an entire case expression makes the difference between compiling correctly and the error "An infinite type was inferred for an expression". The following compiles correctly:
m = case Left "anything" of
e#(Left err) -> Left err
(Right f) -> case lookup "key" f of
Nothing -> Left "something else"
(Just x) -> Right x
However, if we use the pattern variable e (substituting e for "Left err", functionally equivalent), the compiler flags an error:
m = case Left "anything" of
e#(Left err) -> e
(Right f) -> case lookup "key" f of
Nothing -> Left "something else"
(Just x) -> Right x
"An infinite type was inferred for an expression: StrMap t1 while trying to match type t1 with type StrMap t1 while checking that expression case ((lookup "key") f) ...
I understand that matching StrMap t1 with t1 is problematic. I do not understand why this happens. Also, in my original code the message did not refer to infinite types at all. Here is the relevant extract:
retrieveDomeinResourceDefinition :: forall e.
ResourceId
-> Namespace
-> (AsyncDomeinFile e (Either String PropDefs))
retrieveDomeinResourceDefinition id ns = do
df <- retrieveDomeinFile (namespaceToDomeinFileName ns)
case df of
e#(Left err) -> pure $ e
(Right f) -> case lookup id f of
Nothing -> pure $ Left ("retrieveDomeinResourceDefinition: cannot find definition of " <> id <> " in DomeinFile for " <> ns)
(Just propDefs) -> pure (Right propDefs)
retrieveDomeinFile :: forall e. Namespace -> AsyncDomeinFile e (Either String DomeinFile)
newtype PropDefs = PropDefs (StrMap Json)
Now here the compiler tells me: "Could not match type: PropDefs with type StrMap PropDefs..." It appears as if the compiler does not notice the lookup expression. In fact, when I replace "pure (Right propDefs)" with "pure (Right f)", the error goes away (and another appears on the line binding df, which I understand).
Now I write this up I notice the similarity between 'trying to match type t1 with type StrMap t1' and 'could not match type: PropDefs with StrMap PropDefs'. Still, I don't see why using e introduces this problem.
Using the value from a pattern match that way may be functionally equivalent, but the types are not - the type system doesn't have the evidence that the type variable for the Right can be ignored.
Using the types in your second example - when you pattern match e#(Left err), the type of e will be Either String DomeinFile - but you want an Either String PropDefs. The pattern match does not "free up" the type variable on the right, which is why you have to reconstruct the Left with the error again.

Purescript Halogen Component function: Passing spaced arguments instead of a Record?

I'm on PureScript 0.8.2. In PureScript Halogen, the component function has the signature:
component :: forall s f g. ComponentSpec s f g -> Component s f g
where
-- | A spec for a component.
type ComponentSpec s f g =
{ render :: s -> ComponentHTML f
, eval :: Natural f (ComponentDSL s f g)
}
So component expects a record. But in the Halogen Template Project, component is called as follows:
ui = component render eval
Am I looking at two different component functions? or does arguments separated by space get converted into a record? So I tried the following in psci:
> type Point = { x :: Int, y :: Int }
> let
addP :: Point -> Int
addP p = p.x + p.y
> addP {x: 4, y: 5 }
9
> addP 4 5
Error found:
in module $PSCI
at line 1, column 1 - line 1, column 8
Could not match type
{ x :: Int
, y :: Int
}
with type
Int
....
Sorry, the template project hasn't been updated yet. Thanks for the reminder!
Assuming your eval and render functions are in scope you can use field puns to write the component definition this way:
ui = component { render, eval }
But yes, a record is always required now. I'll update the template project right away.

Why does the program work well with the double type and not with float type?

Hi i am a newbie with the haskell programming, i wrote this piece of code:
f :: a->Bool
f x = True
g :: a->Bool
g x = False
class P a where
func :: a->Bool
instance P Integer where
func x = f x
instance P Float where
func x = g x
if i call the function func as func 23.3 Ghci returns the follow error:
<interactive>:6:6:
Ambiguous type variable a0' in the constraints:
(Fractional a0)
arising from the literal 23.3' at <interactive>:6:6-9
(P a0) arising from a use of func' at <interactive>:6:1-4
Probable fix: add a type signature that fixes these type variable(s)
In the first argument of func', namely 23.3'
In the expression: func 23.3
In an equation for it': it = func 23.3
while the code works fine if i call func with an Integer as parameter. If i replace the Float instance of P with a Double instance the code works correctly with the call func 23.3. Why?
This is the infamous Monomorphism restriction. GHCi doesn't know what type to turn 23.3 into specifically, and there are multiple Fractional a data types (notably Double and Float).
You can disable this with
> :set -XNoMonomorphismRestriction
Or better yet
> func (23.3 :: Float)
The reason for this is because the literal 23.3 has type
> :type 23.3
23.3 :: Fractional a => a
Instead of a more concrete type like Float or Int. This actually allows you to implement your own types which can be represented by number literals (a handy trick at times). Unfortunately, it gives a rather unhelpful error message that confuses most every beginner. The compiler has to have a specific type, though, because you could have also added
instance P Double where
func x = undefined
And then it would have to decide which instance of func to use for a literal like 23.3. The best practice is to just specify which type you are using inline like I showed above.
Probably the reason why it worked in GHCi with Double is because GHCi will sometimes attempt to coerce types into something more concrete for convenience. This is why if you were to do
> let x = [1..]
> :type x
x :: [Integer]
When instead x should have type (Enum a, Num a) => [a]. When you have the Monomorphism restriction enabled (by default), GHCi will try to make the types work with Integer, Double, IO, as opposed to Integral a => a, Double a => a or Monad m => m. It just doesn't work well in every case.