Maybe Not - Rich Hickey

  Рет қаралды 155,600

ClojureTV

ClojureTV

Күн бұрын

Пікірлер: 106
@TensorProgramming
@TensorProgramming 5 жыл бұрын
Good old Rich Hickey. Even though I don't use Clojure as much as I should, I still love listening to Rich talk about development every year.
@ethanresnick6456
@ethanresnick6456 2 жыл бұрын
This talk makes Typescript look pretty good (with its true union types, and `Pick` for select), which I guess isn't surprising, given that that JS and Clojure are both highly map-oriented, and Typescript and Spec are shape-oriented optional overlays.
@josevargas686
@josevargas686 7 ай бұрын
Using `Pick` and other utility types in TS is absolutely awful though. First, you need to provide a bunch of string values, already a very ugly thing to do. Second, you can't nest it at all. Third, you have a whole new Type and if your function accepts the Pick and the T, you have to discriminate them at runtime with some hacky if statements like `if(!T.prop)`.
@ryanleemartin7758
@ryanleemartin7758 3 жыл бұрын
Ya know, I've been getting into functional programming for a while, using F# and I learned how amazing Option is (Maybe) and here comes Rich Hickey to laugh in my face. Great talk as always!
@elliottcrifasi3143
@elliottcrifasi3143 2 жыл бұрын
Haha same 😂. It's an improvement on what I had used in other languages, but clojure and this design seem to take that idea and make it even better. I thought Haskell's type system was awesome, but after watching this I'm seeing the benefits of a different way at looking at types/schemas. I'm definitely interested in finding a job using clojure
@lukeyd13
@lukeyd13 Жыл бұрын
Im not a Clojure person anymore but looking at spec in 2022 it seems like it is how rich said it shouldn't be (optionality specified at the aggregate level) rather than in a separate step with selections. Does anyone know what happened to the ideas in this talk I found the answer as of 2022, it’s still in development under the name spec2 there is a GitHub repo
@deveugene7
@deveugene7 5 жыл бұрын
I whole-heartedly approve. Stripes and scarves are definitely the way to go...
@derekfrost8991
@derekfrost8991 5 жыл бұрын
Dr Who.. :)
@Hemigoblin
@Hemigoblin Жыл бұрын
I didn’t realize this till rewatching this talk, but when Rich was first describing Clojure in a talk (maybe in “Clojure Made Simple”), he said that Lisp relying on lists instead of tress was a mistake, and that trees are the better paradigm. In this talk, with his discussion about how spec should change to better handle trees, he’s saying he missed the same lesson, and is trying to fix it.
@janmsavage
@janmsavage 4 жыл бұрын
I don't know what would I have done without Clojure. Lisp is the most important discovery in infotech, and Clojure the most important improvement on a Lisp.
@ZsoltDonca
@ZsoltDonca 5 жыл бұрын
I don't think the issues presented by Rich Hickey with using Maybe or Option are significant, and there are perfectly valid functional solutions. When making parameters optional, one can use Maybe/Option without breaking callers by *introducing a new function*: keep the original's signature as is, introduce a new function with the optional parameter, and make the old function call the new one. Old code still works, and new code can benefit of using the new function without providing a value (passing Empty/None). The same approach works for the return type case as well.
@DenisG631
@DenisG631 5 жыл бұрын
but is it really the same? this way you are kinda lying to your API users by providing same API but with syntactic sugar manual forwarding code. e.g. maybe return by doing extra wrapping, the api caller doesn't know you changed anything inside. He doesn't know that you don't return None anymore. i.e. If you change your signature -> you force the client to make changes in Kotlin, if you change the signature -> your api client is not forced to change anything, but will see that your function doesn't return Optional anymore i.e. in Kotlin syntactic sugar with Optional wrapping is done implicitly in Haskell you have to do forwarding/extra function explicitly AFAIU
@matthiasschuster9505
@matthiasschuster9505 5 жыл бұрын
He did say nothing about Option, just Maybe/Either. Option types (in F#) are real union types, if I am informed correctly.
@mononix5224
@mononix5224 2 жыл бұрын
​@@matthiasschuster9505 sadly you've been misinformed, since Option in F# is a sum type (_disjoint_ union type), not a union type. Given a type T, T Option doesn't have any members in common with T, since all the original members of T have been 'wrapped' by Some. You can think of T Option as being the union of all members of T 'wrapped' by Some and the symbol None, so that you get Some(T) | None, while a union would be T | None. The fundamental difference is the 'wrapping'/'tagging' that happens when making a disjoint union which is absent with simple unions.
@typon1
@typon1 5 жыл бұрын
Another excellent talk by Hickey. Not sure if I buy into his attack on Maybe, but it made me think about it more deeply.
@DanielJomphe
@DanielJomphe 5 жыл бұрын
Funny unintended pun: "...there's a spec-trum of what you can communicate..." (56:50)
@elgireth
@elgireth 5 жыл бұрын
I guess the same argument can be expanded to Lists. If 0..1 can be a *selection* concern and not shape, then 0..* could be too. Maybe specifying the size of the collection as a requirement?
@RobertPankowecki
@RobertPankowecki 5 жыл бұрын
Wonderful and deeply insightful. Thank you!
@TankorSmash
@TankorSmash 2 жыл бұрын
Did s/schema or s/select ever come out? I don't see it in the docs
@johanovlinger9020
@johanovlinger9020 2 жыл бұрын
Karl Lieberherr's work on "adaptive programming" addressed the use of select-like accessors (traversals). That was in the context of imperative java. His group did not really delve in to how to specify requirements on arguments. I imagine that something like go-ish interfaces might work.
@batlin
@batlin 4 жыл бұрын
Typescript and Crystal both have intersection types, although I'm not sure how nice they are to work in practice, nor if the kinds of changes Rich showed in the beginning would still be a breaking change. It's an interesting argument though -- whether the benefits of the compiler's completeness check (i.e. did you handle both Maybe a and Nothing?) and the clarity of the new type signature are greater than the costs of a breaking API change.
@marcellerusu
@marcellerusu Жыл бұрын
> whether the benefits of the compiler's completeness check (i.e. did you handle both Maybe a and Nothing?) and the clarity of the new type signature are greater than the costs of a breaking API change. you get this in kotlin, swift, & strict mode typescript (a common default these days), idk crystal enough tho As in i change my function to `function f(): number | null` in typescript, the consumers will have to check if what's returned is null or not, its just that typescript is powerful enough to not even require runtime wrappers like `Maybe`, it can be statically enforced. Also `number | null` is a different type than `number`
@RequiredAccountsSUX
@RequiredAccountsSUX 5 жыл бұрын
Rich Hickey is the clearest thinker and speaker of his generation that I know. He's on the Guy Steele level.
@freddaoud4432
@freddaoud4432 5 жыл бұрын
Good talk. I understand the point about the spec being separate from the schema. However, this does not solve the problem that Maybe solves. If your function says that x is optional, how do you deal with it if it is present? Are you back to using ifs? This does not provide what Maybe provides, i.e. safe .map, .chain, and so on. Did I misunderstand?
@unformedvoid2223
@unformedvoid2223 2 жыл бұрын
I actually like how your code breaks when you change your function's signature. It helps me to keep my code consistent and find bugs at early stage. Using nullables in C#, undefined and null in JS, undef in Perl wasn't even close to be so pleasant as using Option
@TankorSmash
@TankorSmash Жыл бұрын
Yeah, I'm with you. I don't like that the code breaks at runtime. The computer is smarter than me, I'd like it to help me and tell me what I'm doing wrong. With nice type systems, it's pretty smooth, and you've got so many fewer questions
@aoeu256
@aoeu256 Жыл бұрын
If you don’t what you need since you are programming what you don’t know, and you have thousands of callers it could get annoying😂
@josevargas686
@josevargas686 7 ай бұрын
But it shouldn't break if the requirements are being eased, that's the point... It should break if the requirements are being restricted, but spec does this.
@franciscoflamenco
@franciscoflamenco 6 ай бұрын
The idea isn't that your code shouldn't break, but that it shouldn't break when you're relaxing the conditions. Of course you should go fix everything in your code if a certainty becomes a possibility. But if a possibility becomes a certainty your checks might become redundant, but they shouldn't break your stuff.
@megasuperlexa2
@megasuperlexa2 5 жыл бұрын
the first example does not make sense in case you have implicit cast from a value to its maybe container. And in c# it is super easy (and safe). Not so in f# or other systems I suppose
@robchr
@robchr 5 жыл бұрын
I haven't used the Haskell Lens library but I think it makes it possible to pull out data from nested structures without the user needing to know anything about the structure. This can solve some of the issues with readers of data being polymorphic over any structure.
@pkop4
@pkop4 5 жыл бұрын
Just wondering, why are the root attribute types (50:18) nillable ? Wasn't the point that the base schema should have concrete types (string vs string?) and optionality is handled in the selection?
@trippyoctopus
@trippyoctopus 5 жыл бұрын
They are not nillable. But I think I see the source of confusion. For example, `int?` does not mean “integer or nil” in that slide, instead it refers to the *predicate* `int?` and all it does is test whether a value is of the type int. The description of `:user/id` says that it is only a valid attribute if the value it refers to is an int. Therefore `nil` is an invalid value for that attribute.
@PaulSebastianM
@PaulSebastianM 2 жыл бұрын
45:00 what if you get the user from the wire, from a different context, and you have no idea what the schema contains or doesn't contain, then how can you be sure that you're satisfying the select statement?
@MisterComment25
@MisterComment25 2 жыл бұрын
So, has this actually been implemented and added to spec? Can we use this type of spec he proposed?
@ViktorKronvall
@ViktorKronvall 4 жыл бұрын
There are a lot of inaccuracies about Haskell in this talk. However, there are some good points being brought up. Treating (Maybe x) as a a supertype of x would indeed be nice but subtyping and polymorphic parametricity don’t go that well together. The main issue is that you are losing the great tools of functional programming such as map and fold if you introduce subtyping without giving up and throwing away the type checker. There has been some work to get back a bit more subtyping to Haskell and now the type system is extended to allow subtyping of data that have the same data representation through type preserving coercions. But being able to reason about subtypes created by intersections of required fields would be a nice way to model some functions. Also returning supertypes generated by unions seem ideal. I’m not willing to throw away parametricity but I hope the two perspectives can move closer in the future.
@cryptoAsabiyyah
@cryptoAsabiyyah 5 жыл бұрын
@9:00 why would it break existing callers if the argument is now optional. He explains why it would break for "Maybe returns" but why would it break for a required parameter turned optional?
@gnethercutt
@gnethercutt 5 жыл бұрын
I believe this was a implication that Maybe is an option type (or a monad, if you're feeling frisky), and it alters the function signature and thus callers would need to change invocations like foo(x) to be foo(Maybe.fromValue(x))
@MishaSalnikov
@MishaSalnikov 5 жыл бұрын
because old code is calling `f(a)`, and now it has to call `f(Maybe a)`, so you need to wrap your variable in Maybe to pass it now
@jergason
@jergason 5 жыл бұрын
Hassen Ben-Tanfous you typically have to wrap the value you’re passing in in a type constructor. So to pass in a Maybe String you’d need to wrap the value when calling in Just “my string” or whatever
@WarrenLeggatt
@WarrenLeggatt 5 жыл бұрын
It breaks the caller because they have to pack the argument as Maybe, it switches from a type to a union type. You need to supply "Some x" or None. This all comes down to type theory. Many C languages have nullable types so it does not break the caller but the opposite is also true in that you now have no compiler checks around nullable. C# is about to bring in a breaking change for non-nullable reference types by default. Personally I like Maybe, Either etc as they force the consumer of the value to think about what is contained. Implicit nullability means "null reference exceptions" at run time :)
@andrewkiluk
@andrewkiluk 5 жыл бұрын
Because the type of the input has changed -- if the caller had a line like `foo $ 7`, that must change to `foo $ Just 7` in order to match the new type and compile.
@alexgalays910
@alexgalays910 5 жыл бұрын
Typescript has had unions and intersection types for a long while now :)
@jaredsmith5826
@jaredsmith5826 5 жыл бұрын
Typescript's type system is surprisingly good. But I do have one major beef with it: it can't (at least last time I checked) accurately track the argument types of partially applied functions (FB flow can do this most of the time).
@Ven_de_Thiel
@Ven_de_Thiel 5 жыл бұрын
@@jaredsmith5826 TS recently merged a PR adding return types to the inferencer, so now it should be muuuch better on such things
@sfyire
@sfyire 4 жыл бұрын
Union and intersection types are not the same as schema and selection, selection can be nested in the same way you can use Graphql to express a requirement for multiple keys at different levels
@milosnedeljkovic3737
@milosnedeljkovic3737 5 жыл бұрын
To be fair, no knowledgeable Haskell (or even more broadly, ML family) blogger should (and usually don't, actually) call Maybe or Either a union type. Those are instances of disjoint union type, or else called coproduct (sum). And those are just as precise mathematical terms as simple unions, just with a different semantics. The rest of the talk makes a pretty interesting view of a topic, but this little accusation that Haskell or Scala users are living in some sort of fallacy is a bit unfair
@matthiasschuster9505
@matthiasschuster9505 5 жыл бұрын
Do you know if F# does this right?
@lukasjuhrich503
@lukasjuhrich503 4 жыл бұрын
I'm not sure I'm following you. Doesn't „union“ usually refer to the disjoint union when talking about types?
@szelpsz
@szelpsz 4 жыл бұрын
Yes and no. A mathematical disjoint union / coproduct operator should still be commutative and associative, shouldn't it? A (+) B is ismorphic to B (+) A.
@hoggmann7217
@hoggmann7217 3 жыл бұрын
Came to say something similar, this was way more informative. A+
@DrewIsFail
@DrewIsFail 2 жыл бұрын
"yes and no" so "maybe"? Sorry i couldn't help myself
@bojanmatic024
@bojanmatic024 5 жыл бұрын
Minor nitpick but I think Rich is wrong on the value proposition of parameterized types. A function from List x to List x is telling at least something (that you will return the same data shape as you accept) and it's not obvious that given a List x you will return a List x. You could return a whole lot of things that may or may not have a connection to x or even a list. For example, given a list of strings I could return to you a list of integers. Or a single string. Or a list of maps. Or a list of lists of strings, etc. Otherwise, great stuff. As always.
@Ven_de_Thiel
@Ven_de_Thiel 5 жыл бұрын
`[a] -> [a]` in Haskell means the function can be `reverse`, `id`, `take` (or empty), or replicate the values. Rich wants to make it so that when you see `a -> m a`, it might actually expand to `Maybe a -> Maybe (Maybe a)` which would give `Maybe a -> Maybe a`, and now your signature just became `a -> a` magically!
@cynicist8114
@cynicist8114 4 жыл бұрын
He is just saying that this information is not valuable because it tells you nothing about what the function is actually going to do with the list. It takes a list and returns a list, but you don't even know if it is the same list, just transformed, or maybe a different list entirely. There is no context, and presumably the reason you are asking this question of the function (what are you taking and producing?), is that you are trying to ascertain whether or not it is behaving according to expectations, and types alone don't provide you with that information.
@EvgenyOrekhov
@EvgenyOrekhov 5 жыл бұрын
54:16 [a] -> [a] says exactly that: reverse will return a subset of the same list it was given, because "a" is not a constructor, and "reverse" doesn't know how to instantiate "a", so the result could contain only those elements that was given to the function.
@dlwatib
@dlwatib 5 жыл бұрын
But reverse does not return a subset of [a], it returns a permutation of [a]. And besides, that's not what [a] -> [a] actually says. All it says is that if you give me a list of 'a' you will get back a list of 'a'. There is no guarantee that the 'a's will be from the list you gave me, and there's no requirement that the list I give you wont have a larger cardinality than you gave me. 'a' is a type variable. It can be instantiated to a constructor.
@Ven_de_Thiel
@Ven_de_Thiel 5 жыл бұрын
`[a] -> [a]` can mean that, can mean `id`, can mean `take` (or `empty`), can replicate and turn it into an infinite list (if list was at least length 1), etc.
@DenisG631
@DenisG631 5 жыл бұрын
is it really a subset? can not you prepend/append subarray of the original array?
@isodoubIet
@isodoubIet Жыл бұрын
@@dlwatib This argument is saying essentially "I can't completely specify the behavior of the function in the type system therefore I won't specify anything at all", which is just stupid. From the declaration [a] -> [a] I may not have all conceivable semantic properties of the function (and how could I? that's its _definition!)_ but I certainly know that won't pass a list and get back a zebra.
@csbnikhil
@csbnikhil 8 ай бұрын
The a's have to be from the same list. The function does not know how to create an a.@@dlwatib
@pcaisse
@pcaisse 5 жыл бұрын
I'm not an expert by any means, but at 7:43 it seems like he's using `Maybe` to make an argument optional which I don't think is what you'd do in Haskell -- you'd just create a new function. In pure languages, the type signature is like a contract which describes the function's behavior, what it _must_ do. You wouldn't ever want to change the types a function takes or returns without creating a new function. As such, his gripe seems to stem from a misconception about what a function signature means in a statically typed world.
@dlwatib
@dlwatib 5 жыл бұрын
No, you misunderstand. If you have to create a whole new function in order to make what should be a trivial change, where's your reuse? You've totally failed to reuse your code.
@BjarkeEbert
@BjarkeEbert 5 жыл бұрын
20:02 hehe
@brandonlewis2599
@brandonlewis2599 2 жыл бұрын
I liked this talk, and the speaker's fashion sense. But when changing types leads to type errors ... that's a *feature* not a *bug* ! I *want* to break the caller. I *want* the compiler to find every offending call site. Anything less is unsound. Changing types is breaking an interface. When you break an interface, non-conforming code *should* break at compile time. FlowJS offers true set-theoretic type unions and "type refinements". The good part: you don't have to wrap every nullable in a Maybe at the call site. It fails type-checking if you forget to check for a nullable for null. *That's the point* ! Because when you "just let information flow", you silently allow null (or NaN) to propagate far away from the source of the error. In the limit, You end up with nightmares like log4j.
@tricky2014
@tricky2014 2 жыл бұрын
Its not a feature that when you change your return type from maybe x to x, that the caller breaks. You just increased your guarantee of what you provided. This should be a compatible change and in languages that employ true union types it is. The fact that its necessary that your caller breaks is not dictated by the semantics of the change but the (inadequate) tool you used to express these semantics. Singular types are subtypes of union types that contain them, X is not a subtype of Maybe. Thats a problem. And you can enforce checking for NULL or an error with Union Types too.
@csbnikhil
@csbnikhil 8 ай бұрын
@@tricky2014But the caller would have unnecessary code to handle the possibility of there being nothing even when the function changes the signature to guarantee that there will always be something.
@Ven_de_Thiel
@Ven_de_Thiel 5 жыл бұрын
The Scala program doesn't compile. "Maybe/Either" are not evidence of a lack of first-class union types. No one calls them that, they aren't. It's the same debate as Monad Transformers vs Effects: Do you want `Maybe (Maybe a)` to be a thing, or do you want `a | Nil | Nil` which is `a | Nil`. Just pretending Maybe/Either are bad solutions makes absolutely no sense. Having both is good. You may not care about parametricity, but Haskell people certainly do. "|" being commutative also means you can't have the same type on both sides. Once again. Having both is good. A Haskeller would most probably not using `data Person = Person String String Int Float String String`, it's disingenuous. Haskell people value their types and newtypes. You use types to reason about your program, you'd not use raw Strings floating around. Compare that with Clojure where, not to get lost, people prefix their value keys/keywords with "mytype/". I think I prefer the approach that checks types. "I'm not gonna let you write brittle systems" This has a vibe of "Clojure is the only one doing it right". "You're saying more than any type system let any other people say" . Doing the same thing with key selection is already possible with HLists in Scala and with Generic in Haskell. It's not new, it's just that people generally don't want that. Good talk.
@kahnfatman
@kahnfatman Жыл бұрын
The programmer/engineer/developer himself is part of the use of a programming language. A developer with 30 years of experience can reason without any compiler or IDE assistance. My point is: The tool is just as good as the person who uses it.
@Milhouse77BS
@Milhouse77BS 5 жыл бұрын
Sheep-oriented programming?
Effective Programs - 10 Years of Clojure - Rich Hickey
1:14:52
ClojureTV
Рет қаралды 160 М.
The Language of the System - Rich Hickey
1:02:50
ClojureTV
Рет қаралды 162 М.
Как быстро замутить ЭлектроСамокат
00:59
ЖЕЛЕЗНЫЙ КОРОЛЬ
Рет қаралды 12 МЛН
Hot Ball ASMR #asmr #asmrsounds #satisfying #relaxing #satisfyingvideo
00:19
Oddly Satisfying
Рет қаралды 20 МЛН
Заметили?
00:11
Double Bubble
Рет қаралды 3,3 МЛН
ДЕНЬ РОЖДЕНИЯ БАБУШКИ #shorts
00:19
Паша Осадчий
Рет қаралды 6 МЛН
Are We There Yet - Rich Hickey
1:10:05
Zhang Jian
Рет қаралды 17 М.
"Design in Practice" by Rich Hickey
1:00:46
ClojureTV
Рет қаралды 34 М.
"The Mess We're In" by Joe Armstrong
45:50
Strange Loop Conference
Рет қаралды 376 М.
Clojure Concurrency - Rich Hickey
2:32:39
ClojureTV
Рет қаралды 68 М.
Clojure (the first talk) - Rich Hickey at LispNYC (2007)
1:59:23
Solving Problems the Clojure Way - Rafal Dittwald
1:02:26
Clojure/north
Рет қаралды 71 М.
The Value of Values with Rich Hickey
31:44
InfoQ
Рет қаралды 131 М.
"Transducers" by Rich Hickey
45:00
Strange Loop Conference
Рет қаралды 107 М.
"Simple Made Easy" - Rich Hickey (2011)
1:01:39
ClojureTV
Рет қаралды 64 М.
A History of Clojure by Rich Hickey with Q&A
1:07:02
Visas Meilas
Рет қаралды 29 М.
Теперь это его телефон
0:21
Хорошие Новости
Рет қаралды 2 МЛН
Не обзор DJI Osmo Pocket 3 Creator Combo
1:00
superfirsthero
Рет қаралды 1,3 МЛН
С Какой Высоты Разобьётся NOKIA3310 ?!😳
0:43