Records in PureScript - records

I don't quite understand why this works:
module Records where
type Element e = { element :: String, label :: String | e }
type Sel = ( value :: Number, values :: [Number] )
type Select = Element Sel
while this says Cannot unify # * with *.
module Records where
type Element e = { element :: String, label :: String | e }
type Sel = { value :: Number, values :: [Number] }
type Select = Element Sel
(Note the '()' around the right hand side of Sel instead of the '{}'.)
I've read here https://leanpub.com/purescript/read#leanpub-auto-objects-and-rows that forall r. { firstName :: String, lastName :: String | r } desugars to
forall r. Object (firstName :: String, lastName :: String | r)
I'm still a bit confused, why you can't use the record-sugar for extending records.

The Object type constructor is parameterized by a row of types. In kind notation, Object has kind # * -> *. That is, it takes a row of types to a type.
( value :: Number, values :: [Number] ) denotes a row of types (something of kind # *), so it can be passed to Object to construct a type, namely
Object ( value :: Number, values :: [Number] )
Note that { ... } is just syntactic sugar for the Object type constructor, so this is the same as
{ value :: Number, values :: [Number] }
Both have kind *, so it doesn't make sense to pass this thing as an argument to Element, since the type variable e in Element has kind # *.
Put another way, Element Sel in your second example unrolls to
{ element :: String, label :: String | { value :: Number, values :: [Number] } }
which desugars to
Object (element :: String, label :: String | Object (value :: Number, values :: [Number]) )
which fails to kind-check due to the thing of kind * in the tail of the outer row.

Related

Is it possible in Fortran to determine if two polymorphic objects are the same derived type?

Is it possible to take two polymorphic objects and determine if they are of the same derived type (or class)? The intention is to use it as a clean way to filter a generic linked list.
Something like the following mock code.
function isSameType(a, b) result(itIs)
!arguments
class(*), intent(in) :: a
class(*), intent(in) :: b
!output
logical :: itIs
!return true if a and b are both the same type
!return false if a and b are not
end function isSameType
The standard inquiry function same_type_as tests equality of dynamic type of two objects:
program typetest
implicit none
type t1
end type t1
type t2
end type t2
class(*), allocatable :: a, b
allocate(t1 :: a)
allocate(t2 :: b)
print *, SAME_TYPE_AS(a,b) ! False
end program
same_type_as does not test declared type (except where this is the same thing). It does not consider kind parameters:
program partest
implicit none
type :: t1(n)
integer, kind :: n
end type t1
type(t1(1)) :: a
type(t1(2)) :: b
print *, SAME_TYPE_AS(a,b) ! True
end program
Further, to get a useful result you'll be wanting (at least) one of a and b to be of extensible dynamic type. While you can ask
program intrinsictest
implicit none
class(*), allocatable :: a, b
allocate(real :: a)
allocate(double precision :: b)
print *, SAME_TYPE_AS(a,b) ! ...
end program
the result is processor dependent (could be true or false).

Fortran syntax for assignments

The Fortran syntax is driving me mad! Can anyone explain how I can call the assignment (I'm pretty sure that is not the right terminology either...). I'm trying to assign a type according to the value type. I have the following:
module test_module
implicit none
type :: mytype
integer :: i
real :: r
logical :: l
contains
generic :: assignment(=) => mytype_to_type
procedure, pass(me) :: mytype_to_type
end type mytype
contains
subroutine mytype_to_type(t, me)
implicit none
class(*), intent(inout) :: t
class(mytype), intent(in) :: me
!.. process based on input type
select type (t)
type is (integer)
t = me%i
type is (real)
t = me%r
type is (logical)
t = me%l
class default
stop "none"
return
end select
end subroutine mytype_to_type
end module test_module
program test
use test_module
implicit none
type(mytype) :: t_type
integer :: i = 1
real :: r = 1.
logical :: l = .true.
t_type = i !! how is this supposed to work?
select type(t_type)
type is (integer)
write(*,*) "is int"
type is (real)
write(*,*) "is real"
type is (logical)
write(*,*) "is logical"
class default
return
end select
end program test
Would this even work? Could anyone help me with this?
Thanks!
In a subroutine supporting defined assignment the two arguments are such that the first corresponds to the left-hand side of the assignment statement and the second the right-hand side.1
Here, then the subroutine you provide is assignment from a my_type expression to an unlimited polymorphic object. This isn't what you want, seeing t_type on the left.
Instead, you should provide defined assignment to a my_type object.
subroutine stuff_to_mytype(me,t)
class(mytype), intent(out) :: me
class(*), intent(in) :: t
!.. process based on input type
select type (t)
type is (integer)
me%i = t
type is (real)
me%r = t
type is (logical)
me%l = t
class default
stop "none"
return
end select
end subroutine stuff_to_mytype
That said, you could do this with a specific subroutine for each type you support, rather than an unlimited polymorphic right-hand side, with generic resolution. In this case you could also consider generic structure constructors (t_type=mytype(i)).
1 Precisely, the second argument is the right-hand side enclosed in parentheses.

What does the double colon ( :: ) mean in Elm?

I'm new to Elm and I just came across this:
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
UrlChange location ->
( { model | history = location :: model.history }
, Cmd.none
)
Could someone tell me what the double colon does in line 5?
That's the cons operator. It adds an item to the front of a list.
1 :: [2,3] == [1,2,3]
1 :: [] == [1]
Documentation:
https://package.elm-lang.org/packages/elm/core/latest/List#::

How to fix this Purescript error: Could not match {...} with (...)?

I have a state for a halogen component including a lens like this:
import Optic.Core (Lens', lens)
type State =
{ userName :: String
, password :: String
, formError :: String
}
_userName :: Lens' State String
_userName = lens _.userName (\r str -> r { userName = str })
And I want to modify the state in the eval function of the same component like this:
eval :: forall eff.
Query ~> ParentDSL State Query UserNameField.Query Slot Void (Aff (console :: CONSOLE , ajax :: AJAX | eff))
eval = case _ of
HandleInput userName next -> do
-- this code causes trouble:
_userName .= userName
-- while this code works:
-- modify (set _userName userName)
pure next
However, I get the error message:
Could not match type
{ userName :: String
, password :: String
, formError :: String
}
with type
( userName :: String
, password :: String
, formError :: String
)
while trying to match type t3
{ userName :: String
, password :: String
, formError :: String
}
with type t2
while checking that expression _userName
has type (t0 -> t1) -> t2 -> t2
in value declaration eval
where t1 is an unknown type
t0 is an unknown type
t2 is an unknown type
t3 is an unknown type
[TypesDoNotUnify]
Note the difference between { and ( (took me a while). I don't even know what the latter type actually means and I have no clue why this error is introduced by a MonadState-based lense.
Mystery solved: I unintentionally mixed two packages
purescript-lens and purescript-profunctor-lenses. My lenses came from the former and the assign function (.=) is only present in the latter, which was installed apparently as some implicit subdependency.

Discriminated union type checking in F# with differernt return types

I am trying to write an interpreter in F#. I want to check the type of expressions.
Here is my discriminated union for the expressions
type Expr =
| Integer of int
| String of string
| Boolean of bool
This is the method i am using to check the types with
let checkType (e:Expr) =
match e with
| String s -> s
| Integer i -> i
| Boolean b -> b
I want the method to determine wether an expression is a string,integer or boolean.
However, visual studio gives me the following error on line 4 of the checkType method:
This expression was expected to have type string but here has type int
Am i missing something?
To expand on John Palmer's comment:
F# expects each function to have a single return type. For example, you can write a function that takes an int and returns an int, which would be a function of type int -> int. A function that parses strings into ints would be of type string -> int. And so on.
Now, what is the return type of the checkType function you've written? Since you don't specify a return type, the compiler looks at the type of the values you can return from the function -- every possible code branch must return a value, and they must all be the same type. So it looks at your match statement, sees that its first branch returns a string, and says, "Ah ha! I've figured out the return type of this function; this is a function that takes an Expr and returns a string. The function's type is Expr -> string."
Then it looks at the second branch of your match statement, and says, "Wait a minute. This is a function that returns a string, but in this code branch it's returning an int. That's not valid: the code that calls this function needs to know what type to expect it to return." And so you get the error.
Now, if you were to swap the order of your match statement cases, checking for Integer i first, then the compiler would evaluate your function as having type Expr -> int (taking an Expr input and returning an int output), and throw an error on the | String s -> s line. This time, the error would be "Wait a minute, this is a function that returns an int, so the expression s here should have been of type int. But instead, it's of type string. That's not valid."
Or delete the | String s -> s line, and you'll see an error "This expression was expected to have type int but here has type bool." Same thing: each function can have only one return type. If you want to return multiple different possible types from a function, that's what Discriminated Unions are for.
For more reading on F# types, see http://fsharpforfunandprofit.com/series/understanding-fsharp-types.html.
You can wrap all of the expressions into an Option type like Some or String:
let checkType (e:Expr) =
match e with
| String e -> "we are string: " + string e
| Integer e-> "we are integer: " + string e
| Boolean e -> "we are boolean: " + string e

Resources