/tech/ - Tech


Mode: Reply

Max message length: 8192


Max file size: 20.00 MB

Max files: 3


(used to delete files and postings)


Remember to follow the rules

>>1944 you cant compare c to haskell, haskell is a garbage collected language
(162.51 KB 708x933 plebbit soy 467.jpg)
>>1945 >defends bloat Spoken like a true mon*id
>>1946 ok Cfag have fun programming in your language from 1966
>c is faster than Haskell No shit. That isn't the point of functional programming you speed obsessed bugcuck
I just want a language that has Haskell's typing system and treats functions as variables without all the bloated "function purity" garbage
>>1968 Basically every modern language has functions as variables nowadays. Though have fun with it not optimising for tail calls in highly recursive functions though lol. What's so special about Haskell's typing anyway? (Also pureity is fucking good but if you want a language almost as powerfull as Haskell that allows you to shoot yourself in the foot of you reeeeeaaaaaly wanted very hard to, try fsharp, it also seemlessly interops with csharo so you can just write a library in fsharp and use it in csharo and vice versa.)
>>1968 not a rustfag but doesnt rust have some FP properties?
>>1969 >What's so special about Haskell's typing anyway? type synonyms make code so much more readable (especially when dealing with bools) and makes data structures easier to define on fewer lines of code. also typeclasses are nice since it pretty much forces the programmers to use existing operators without just writing a method for every damn operation. just makes advanced math elements a lot nicer to work with compared to what I've seen in other languages.
(76.60 KB 600x536 lmao.jpg)
>>1961 imagine using a language that's at the same time bloated and doesn't even support for loops
(61.78 KB 559x676 gamer soy 324.png)
>>1964 >akhshually, bloat is good The absolute state of monoids
>>1978 >abstractions are bad >t. not an engineer Enjoy writing the same thing over and over for slightly different scenarios. And enjoy callback hell, you deserve it.
(32.64 KB 400x400 looplet.png)
>>1979 Imagine unironically liking functional programming. >no loops looplets btfo
>>1981 why do you need loops though? map and fold has almost all your needs covered.
(262.68 KB 328x820 t.png)
FP might be ok if you had a lang that didn't need a massive runtime, but it's still masochistic as fuck trying to solve problems in that paradigm.
>>1983 Who even uses recursion. I can't really wrap my head around it. Just map and fold everything. >>1984 I've heard you get used to it. I'm not really there yet though. I enjoy the strong typing because I hate writing unit tests. Especially javascript unit tests which are basically just typechecking everything manually.
>>1985 >I enjoy the strong typing because I hate writing unit tests If all you want is strong typing, then what is even the point of haskell? Use rust, c#, or any other strongly typed language. You won't have to check types manually, and you also avoid all the pure functional autism.
>>1986 Haskell has more things I enjoy, like purity, monads, non-OOP, create your types for everything, partial application, completeness (non nulls). Haven't really gotten into typeclasses, but it's nice that you can declare your types have certain properties and/or functions and you get a shit ton of functions for free, like monoids, functors, etc, but also stuff like serializers and shit. Programming in haskell feels like bowling with the side protectors on, a lot of stupid shit gets caught very early on.
>>1985 >non-OOP >create your types for everything So something like C structs or rust enums? >monads Buzzword. >but it's nice that you can declare your types have certain properties and/or functions How's that not OOP? Not sure what you mean by types having functions, but all OOP languages have methods already.
>>1988 meant for >>1987
>>1988 >So something like C structs or rust enums? C structs are not type safe at all, so no on that regard. And there's a strong preference for immutable structures over mutable ones, so no on that regard either. The immutability by default makes it easier to reason about things and it also makes testing easier, when compared with variables which might lose their value or change to something undesirable. Otherwise, yes, they are similar in the sense that they represent ad-hoc data structures. >Buzzword Not really, there's some properties of monads which make programming certain things very clean and composable. The joke "A monad is just a monoid in the category of endofunctors, what's the problem?" really sums it up, a monad is just a class of objects that behaves like numbers under addition. Like 1 + 1 = 2, 1 + 0 = 1, except with "objects". The nice thing is that there's a lot of syntax sugar that makes working with monads nice. And because of type classes, you can hide a lot of the complexity of the ""addition"" to the description of the type itself. This is kind of like making methods on objects. This is similar to OOP if all classes that have the trait "monad" had a ".join()" and a ".emptyConstructor()" method, but also all values are immutable. On top of that, Haskell has nice syntax which "pipe" one resulting monad to the next function. Which at the end means you can pipe things like `m1 >> func1 x y >> func2 x y` and the whole machinery will take care of itself. On top of that, if something is off, the compiler will tell you. This means you can offload a lot of complexity by blindly trusting the underlying implementation and build upon abstractions. This doesn't really translate to normal OOP, because everything needs to be modified "manually", described fairly mechanically, and you always need to have knowledge about all the moving parts. Stuff like a failing chain of operations: `m1 >> funcMightFail1 x >> funcMightFail2 >> funcMightFail3 >> funcMightFail4` Where each function expects a non-failing parameter as input. The >> operator basically takes care of that for you. If at some point something fails, it just stops executing the rest of the functions. This is validated by types, by making your functions only accept non failing variables, you ensure that the >> operator is working correctly and that your program can never improperly arrive at such situation, and hence, you don't even consider it. In an imperative setting this would have to look something like: C var x = funcMightFail1(x, m1); if (!x) return null; var y = funcMightFail2(x); if (!y) return null; var z = funcMightFail3(y); if (!z) return null; var k = funcMightFail3(y); if (!k) return null; // ... continue program As you can see, that is extremely error prone and I even left a nice error in there for fun.
(93.36 KB 1200x816 haskellsoy.png)
>>1987 >purity >he enjoys functional cuck restrictions Imagine passing functions as arguments like a virgin, instead of taking all functions you want from the global namespace like a chad.
>>1991 You're mixing up concepts. Restrictions are a clean kink. Dirty kinks is eating poop and spending time on type bugs. Once you stop fighting the compiler, it becomes a truly symbiotic relationship where you can do whatever the fuck you want and the compiler has your back. I'd like to see someone program as fearlessly as they do in ML style languages as they do in php or some shit.
(105.66 KB 1242x1418 2zj1zn0dfo641.jpg)
>>1992 >you can do whatever the fuck you want and the compiler has your back What if I want to use loops and mutable data?
>>1981 >Too dumb for recursion Lol stay mad brainlet
>>1983 Tail end recursion works exactly like a loop. Except without all the retarded mutability.
>>1991 I bet you like working in a factory without protective railings. I'm sure it's super usefull for that one time you one dropped down from the second floor via a car that happened to be standing there.
>>1993 >Loops Tail end recursion >Mutability Not needed unless you're a brainlet or doing circular graphs.
(180.79 KB 640x590 soy 432.jpg)
>>1990 (You can implement monads in Oop with good enough generics and anonymous functions though but you have to be carefull not to mutate anything)
>>1999 >Copy the entire structure Brainlet detected. Most cases you won't need to copy most of it because the data is immutable so most of it is just reused. Do you have any other arguments other than rage comics?
>>2001 >modifying immutable data does not copy data lmao, that's literally how immutable structures work. Copy everything into a new structure, change some shit, and delete the old structure. I think this and recursive calls is a good explanation for haskell's java-tier memory usage, unless you as a mon*id have some better explanation.
>>2002 You have no idea what youre talking about. For example, if you have this structure { field1: 20 subfield: { field2: 60 } } If you change field1, you just create a new structure but you reuse subfield, and whatever other non primitive values may exist in the backend. Also, you dont copy and then modify, you create a new one using exsting and new values and subvalues. What you similarly do not understand is that tail call optimisation, used for the most common type of recursion, is not any more memory intensive than loops. A tail end recursion is when a logical tree ends with "return recursivefunction(args)". In oop it would excecute the function in a new stack frame (and since its recursive many such frames), but in functional programming, since all data is immutable and thus can be used as if it is a new value, it can just create a new stackframe for the function with the variables, delete the old stack frame, then excecute the function, leaving you with one one actively excecuted stack frame. With tail call recursion, the optimised might probably not even make a new stack frame, since it can just substitute the current frames top level args with the new values (but it might because creating 1 temporary stack frame rather than 0 makes hardly any difference so this edge case isnt worth optimizing). What is your goal with a programming language? That everything looks like this: error err = somefunc(args); if(err != null){ return err; } err = somefunc2(args); if(err != null){ return err; } err = somefunc3(args); if(err != null){ return err; } err = somefunc4(args); if(err != null){ return err; } Or this? return somefunc args >> bind somefunc2 args>> bind somefunc3 args>> bind somefunc4 args
>>2003 And note that that example is still needlessly verbose With a custom operator you can do: return somefunc1 args >>. somefunc2 args >>. somefunc3 args >>. somefunc4 args
(1.92 MB 1099x1600 lesboid.png)
I hope you never use natural numbers for anything if you are so much against monoids, otherwise you'd be a hypocrite. Like numbers assigned to posts in this thread, the count of the inb/reddit/ch memes you have hoarded or the number of the SICP chapter that filtered you.
(168.33 KB 645x426 soyvschad 341.png)
>>2005 Good thing I'm not a (((monoid))), so i don't have to care about your buzzwords.
>>2006 Numbers are litterally monoids and monoids are used in every good piece of data processing software.
>>2003 If you're a soy boy who's scared of manually checking errors, you can do someFunc(args); someFunc2(args); someFunc3(args); someFunc4(args); but in a language that supports exceptions.
>>2007 I'd like to interject for a moment. What you're referring to as functional programmers, is in fact, functional autists, or as I've recently taken to calling it, monoids.
(98.71 KB 1000x1500 monoid.jpg)
>>2010 forgot pic
>>2009 >I love exceptions Have fun not catching your errors. Also we can keep playing this game but I will just put the option type on the table which means you don't have to check null for all your arguments because null doesn't exist. It also has bind and lift methods. But I bet you're gonna say >I actually love checking if my values are null >Actually I love having null exceptions when I forgot to check it manually >I love the fact that even after I null check a type I cannot let the compiler know the value is not null Fag
>>1969 >Also pureity is fucking good but if you want a language almost as powerfull as Haskell that allows you to shoot yourself in the foot what is so good about purity and why is it shooting myself in the foot to think otherwise? purity might not be a problem if you're doing simple console i/o but if you're dealing with extremely complex outputs (such as OpenGL for a videogame) it becomes such a pain in the ass since you have to integrate non-pure ideas like time flow and coincident events into the pure world of haskell. which results in so many workarounds and operators that all of your code is 99% likely to be completely unreadable.
>>2017 Not all applications are appropriate for Haskell. But regarding what you said about time and stuff, there's a lot of research done in FRP, which explicitly deals with purity in time varying scenarios. It cuts down on complexity massively but unfortunately, it is not fast or memory lean enough to use for AAA games. A lot of ideas have been borrowed from it and ported into imperative languages. From what I understand, React.js borrowed heavily from FRP. Elm did as well, although that is a functional language. Playing with Reflex was really fun, very mind bending, almost like magic. I'm looking into purescript for interesting libraries, specifically Concur. To answer your first question, purity is nice because you can isolate functions and "prove" they are correct. The nice thing about purity is that they will always give the same result given the same input, which means that if you test a shit ton of random inputs and it behaves as expected, it will probably behave as expected in production. I try to use purity in imperative languages since it makes it much easier to reason about data flow. This means that stuff is not mutated in hidden places, it is always clear where the data has changed. But OOP makes this very cumbersome. In imperative languages it means being very diligent in not modifying the arguments. This has several problems, one is that you either have to make a new datastructure to be returned or you must copy the entire object and return it instead. The cost of copying large structures is very steep. There's also a billion pitfalls with the depth of copying, you might accidentally be mutating another object's nested field because you didn't copy correctly. Not only that, copying objects is very unweildy code-wise beyond a simple shallow copy. This also means that you have to hand code every single class you want a deep copy of. Then there's the issue of colliding programming styles. People are very used to just mutating everyhing everywhere. Which is fine, because it makes code more legible. But if you want to make pure functions, there might be problems with your team. And finally purity goes against OOP, which uses methods for mutation and tries to encapsulate complexity. If you are shooting for a pure approach, you will probably be breaking this encapsulation and you will be left with a confusing mess of non-OOP code and OOP code, making it really hard to understand where things are happening.
>>2006 Is that your template answer when you didn't understand anything that was said? I didn't expect the concept of natural number to filter you as well.
>>1946 >>1978 >>1981 >>1983 >>1991 >>1999 >>2006 >>2007 >>2011 thank you for your service, soyjacker.


no cookies?