3 ms·
Sure, let's roll with that. How would you write a function parameter that takes two arguments, whose type is determined by the seed argument? Also, with reduc
by sillysaurus3 9y ago
Sure, let's roll with that.
How would you write a function parameter that takes two arguments, whose type is determined by the seed argument?
Also, with reduce, the return value of the function can determine what the type of the input arguments should be. For example if you pass in a `(fn (x y) (list x y))`, you end up with:
> (reduce (fn (x y)
(list x y))
(list "a" "b" "c" "d"))
("a" ("b" ("c" "d")))
Let's throw in a print statement to print out the `y` parameter:
> (reduce (fn (x y)
(print (str y))
(list x y))
(list "a" "b" "c" "d"))
"d"
("c" "d")
("b" ("c" "d"))
("a" ("b" ("c" "d")))
So `y` starts out as a string, then a list of strings, then a list whose first element is a string and the second element is a list of strings, and so on.
I'm not sure what the type of that function would even look like. And if there's no way to express something as simple as `reduce` without resorting to `f: (x: Any, y: Any) -> Any`, are we certain it's good design?
- wolfgang42 9y ago> How would you write a function parameter that takes two arguments, whose type is determined by the seed argument? I feel like I'm missing something here. I would think it would just be reduce<I, O>(fn:(O, I|O)=>O, seed:I): O
- sillysaurus3 9y agoHow would you call it? I'm interested in how you'd specify `I` and `O`. `I` is obviously a string, but it seems like `O` needs to be at least three different types: > (reduce (fn (x y) (list x y)) (list "a")) "a" > (reduce (fn (x y) (list x y)) (list "a" "b")) ("a" "b") > (reduce (fn (x y) (list x y)) (list "a" "b" "c")) ("a" ("b" "c"))
- lilactown 9y ago`O` would be whatever the type of the reducer is, so for `list` in the lisp you're using (is it Clojure? The function params look wrong) has a type signature `(A, B?, ...Z?) -> A | List(A, B, ...Z)`. So the transducer in this case would have the type `List(A, B?, ...Z?) -> A | List(A, B | List(B, ...etc))` It's not three different types, but it is necessarily recursive, which seems tricky.
- deleted 9y ago[deleted]
- Veedrac 9y agoThe type of the reduction function would just be something like (X, Y) -> (X Y) args pair The type of a reduce that has an initial seed is something like X -> ((E, X) -> X) -> [E] -> X seed reducer list result The result is going to need to be some recursively defined type, which I'll call List, type List E = E | (E (List E)) Apply these together trivially (List E) -> ((E, (List E)) -> (List E)) -> [E] -> (List E)
- BoiledCabbage 9y agoAnd this is the other thing I like about the haskell/ML collection of languages. The description you gave above is extremely concise and direct. If you're familiar with the language being used it's a very efficient form of communication. I've noticed that working in languages of that family gives you a vocabulary to talk about things that previously would have been very wordy to discuss. Languages with these types of type features provide easy abstractions to illuminate structure and patterns begin discussing new ideas that previously would've been considered on off code.
- Veedrac 9y agoFWIW, this can be inferred fully automatically. Type let pair = fun x -> fun y -> { _0 = x; _1 = y } let rec reduce = fun init -> fun combine -> fun xs -> match xs with [] -> init | x :: rest -> reduce (combine x init) combine rest let test = reduce 0 pair [1; 2; 3; 4] into https://www.cl.cam.ac.uk/~sd601/mlsub/ https://www.cl.cam.ac.uk/~sd601/mlsub/ to see a demonstration.