Say I have this record:
type alias Rec = { a : Int }
And, for example, a function that takes two of these and sums their integers.
f: Rec -> Rec -> Int
This can be implemented using record accessors (i.e. f x y = x.a + y.a), but is there a way to use pattern matching to extract both integers?
Obviously, these two do not work because they would be binding two different numbers to the same variable:
f {a} {a} = a + a
f x y = case (x, y) of ({a}, {a}) -> a + a
There seems to be no such way in the current Elm language. In other functional languages such as ML and Haskell, you could write patterns inside records like:
$ sml
Standard ML of New Jersey v110.74 [built: Sat Oct 6 00:59:36 2012]
- fun func {field=x} {field=y} = x+y ;
val func = fn : {field:int} -> {field:int} -> int
- func {field=123} {field=45} ;
val it = 168 : int
You might as well make a feature request to the developer(s) of Elm - or ask a question in the community mailing list at least.
P.S. After a quick search, I found such a proposal to add ML-like pattern matching on record fields in Elm, but it seems to have been turned down.:-(
There's no way to do this currently. There is pattern aliasing (as) but it only works for a whole pattern, so this is invalid:
type alias Rec = { a : Int }
f: Rec -> Rec -> Int
f { a as xa } { a as ya } = xa + ya
main = f { a = 1 } { a = 2 }
results in:
Detected errors in 1 module.
-- SYNTAX PROBLEM --------------------------------------------------------------
I ran into something unexpected when parsing your code!
4| f { a as xa } { a as ya } = xa + ya
^
I am looking for one of the following things:
a closing bracket '}'
whitespace
Related
I know that I can run monadic instructions sequentially inside monads in Kind language, like this:
Test: _
IO {
IO.print(Nat.show(2))
IO.print(Nat.show(3))
IO.print(Nat.show(4))
}
output:
2
3
4
But is it possible to run monadic instructions repeatedly, like this below?
Test: _
a = [2,1,3,4,5]
IO {
for num in a:
IO.print(Nat.show(num))
}
If it is possible how can I do it correctly?
Monads are usually represented by only two operators :
return :: a -> m(a) // that encapulapse the value inside a effectful monad
>>= :: m a -> (a -> m b) -> m b
// the monadic laws are omitted
Notice, the bind operator is naturally recursive, once it can compose two monads or even discard the value of one and the return can be thought of as a "base case".
m >>= (\a -> ... >>= (\b -> ~ i have a and b, compose or discard? ~) >>= fixpoint)
You just have to produce that sequence, which is pretty straightforward. For example, in Kind we represent monads as a pair which takes a type-for-type value and encapluse a polymorphic type.
type Monad <M: Type -> Type> {
new(
bind: <A: Type, B: Type> M<A> -> (A -> M<B>) -> M<B>
pure: <A: Type> A -> M<A>
)
}
In your example, we just have to trigger the effect and discard the value, a recursive definition is enough :
action (x : List<String>): IO(Unit)
case x {
nil : IO.end!(Unit.new) // base case but we are not worried about values here, just the effects
cons : IO {
IO.print(x.head) // print and discard the value
action(x.tail) // fixpoint
}
}
test : IO(Unit)
IO {
let ls = ["2", "1", "3", "4", "5"]
action(ls)
}
The IO as you know it will be desugared by a sequence of binds!
Normally in case of list it can be generalized like the mapM function of haskell library :
Monadic.forM(A : Type -> Type, B : Type,
C : Type, m : Monad<A>, b : A(C), f : B -> A(C), x : List<A(B)>): A(C)
case x {
nil : b
cons :
open m
let k = App.Kaelin.App.mapM!!!(m, b, f, x.tail)
let ac = m.bind!!(x.head, f)
m.bind!!(ac, (c) k) // the >> operator
}
It naturally discard the value and finally we can do it :
action2 (ls : List<String>): IO(Unit)
let ls = [IO.end!(2), IO.end!(1), IO.end!(3), IO.end!(4), IO.end!(5)]
Monadic.forM!!!(IO.monad, IO.end!(Unit.new), (b) IO.print(Nat.show(b)), ls)
So, action2 do the same thing of action, but in one line!.
When you need compose the values you can represent as monadic fold :
Monadic.foldM(A : Type -> Type, B : Type,
C : Type, m : Monad<A>, b : A(C), f : B -> C -> A(C), x : List<A(B)>): A(C)
case x {
nil : b
cons :
open m
let k = Monadic.foldM!!!(m, b, f, x.tail)
m.bind!!(x.head, (b) m.bind!!(k, (c) f(b, c)))
}
For example, suppose that you want to sum a sequence of numbers that you ask for the user in a loop, you just have to call foldM and compose with a simple function :
Monad.action3 : IO(Nat)
let ls = [IO.get_line, IO.get_line, IO.get_line]
Monadic.foldM!!!(IO.monad, IO.end!(0),
(b, c) IO {
IO.end!(Nat.add(Nat.read(b), c))
},
ls)
test : IO(Unit)
IO {
get total = action3
IO.print(Nat.show(total))
}
For now, Kind do not support typeclass so it make the things a little more verbose, but i think a new support to forM loops syntax can be thought in the future. We hope so :)
I created a function p that checks if the square of a given value is lower than 30.
Then this function is called in an other function (as argument) to return the first value inside a list with its square less then 30 ( if p is true, basically I have to check if the function p is true or false ).
This is the code :
let p numb =
let return = (numb * numb) < 30 in return
let find p listT =
let rec support p listT =
match listT with
| []-> raise (Failure "No element in list for p")
| hd :: tl -> if p hd then hd
else support p tl in
let ret = support (p listT) in ret
let () =
let a = [5;6;7] in
let b = find p a in print_int b
But it said on the last line :
Error: This expression (p) has type int -> bool
but an expression was expected of type int -> 'a -> bool
Type bool is not compatible with type 'a -> bool
However, I don't think I'm using higher order functions in the right way, I think it should be more automatic I guess, or not?
First, note that
let return = x in return
can replaced by
x
Second, your original error is on line 10
support (p listT)
This line makes the typechecker deduce that the p argument of find is a function that takes one argument (here listT) and return another function of type int -> bool.
Here's another way to look at your problem, which is as #octachron says.
If you assume that p is a function of type int -> bool, then this recursive call:
support (p listT)
is passing a boolean as the first parameter of support. That doesn't make a lot of sense since the first parameter of support is supposed to be a function.
Another problem with this same expression is that it requires that listT be a value of type int (since this is what p expects as a parameter). But listT is a list of ints, not an int.
A third problem with this expression is that it only passes one parameter to support. But support is expecting two parameters.
Luckily the fix for all these problems is exremely simple.
fun <I, O> ((I) -> O).modify(modifier: (I, (I) -> O) -> O): (I) -> O =
{ modifier(it, this) }
#Test
fun modify() {
assertEquals(
200.0,
{ x: Double -> x + 100.0 }
.modify { x, parent -> parent(sin(x)*100.0) }(PI/2)
)
}
What I want is to turn a unary function F1(x) into another unary function F2(x) that uses the first function in some way. Am I reinventing the wheel here? Does this functional operation already have some more specific name than "modify"?
So, in functional, curried syntax that would be
modify :: (i -> o) -> (i -> (i -> o) -> o) -> i -> o
modify f modifier x = modifier x f
Note that you're not actually using the fact that the second argument of modifier is a function, i.e. this is strictly a specialisation of
modify :: a -> (i -> a -> o) -> i -> o
modify a modifier x = modifier x a
which can be written
modify a modifier x = flip modifier a x
...allowing us to η-reduce it to
modify a modifier = flip modifier a
The flip itself can be flipped too:
modify a modifier = flip flip a modifier
...and we can η-reduce the rest too:
modify = flip flip
Whatever this is worth.
On another thought, (i -> o) -> o is the characteristic signature of continuation-passing style, so perhaps that's what you're re-inventing here.
Your test case looks like what you mostly want is a way to pre-process the argument of a function. That, as Marko Topolnik already commented, is simply composition
assertEquals(
200.0,
({ x: Double -> x + 100.0 }
compose { x -> sin(x)*100.0 }) (PI/2)
)
(Not sure I've got the Kotlin syntax right there)
I defined a higher-order function like this:
val func : int -> string -> unit
I would like to use this function in two ways:
other_func (func 5)
some_other_func (fun x -> func x "abc")
i.e., by making functions with one of the arguments already defined. However, the second usage is less concise and readable than the first one. Is there a more readable way to pass the second argument to make another function?
In Haskell, there's a function flip for this. You can define it yourself:
let flip f x y = f y x
Then you can say:
other_func (func 5)
third_func (flip func "abc")
Flip is defined in Jane Street Core as Fn.flip. It's defined in OCaml Batteries Included as BatPervasives.flip. (In other words, everybody agrees this is a useful function.)
The question posed in the headline "change order of parameters" is already answered. But I am reading your description as "how do I write a new function with the second parameter fixed". So I will answer this simple question with an ocaml toplevel protocol:
# let func i s = if i < 1 then print_endline "Counter error."
else for ix = 1 to i do print_endline s done;;
val func : int -> string -> unit = <fun>
# func 3 "hi";;
hi
hi
hi
- : unit = ()
# let f1 n = func n "curried second param";;
val f1 : int -> unit = <fun>
# f1 4;;
curried second param
curried second param
curried second param
curried second param
- : unit = ()
#
I'm looking for a way to do while-loops or for-loops in Miranda.
I'm trying to do something like
while(blablanotfinished)
{
if(a=true)blabla
else blabla
}
Miranda doesn't have while- or for-loops (which wouldn't make much sense without mutable state anyway). In most cases you can use higher order functions instead. In cases where there is no higher-order function which does what you need, you can use recursion.
For example if you have the following while-loop in an imperative language:
f(start) {
x = start
while( !finished(x) ) {
x = next(x)
}
return x
}
You would express it recursively in Miranda like this:
f x = if finished x then x else f (next x)
In Miranda (and in general, in purely functional programming languages) the use of looping constructs like WHILE, FOR, etc. is discouraged. You're expected to do iteration via recursion.
Like many other functional languages, Miranda does not have for- or while-loops. Instead, you write loops using recursion, list comprehensions or higher-order functions.
while/repeat/for-loops in functional programming style look like this:
while :: (*->bool) -> (*->*) -> * -> *
while p ff state
= state , if ~ (p state)
= while p ff (ff state), otherwise
Sample: Add number to its reverse until it is a palindrome.
Hints: Start value 196 leads to VERY big numbers.
isPalindrome :: num -> bool
isPalindrome n = (str = reverse str) where str = shownum n
addPalindrome :: num -> num
addPalindrome n = n + rev where rev = (numval.reverse.shownum) n
test196 :: num -> num
test196 n = while ((~).isPalindrome) addPalindrome n
test = test196 89
I hope, somebody is still interested in Gofer/Miranda/Haskell.
Annemarie Paysen (Germany)