Tänkte kolla om någon är en fena på Haskell här (vet inte om samma saker gäller för alla funktionella språk). Hej! Nyckelordet <b>do</b> används tillsammans med monader, som kan sägas vara den funktionella världens implementation av sekvensiell programmering. Nej, Dan. Det är inte samma, men tack ändå. =) Antagligen är det problem med indraget så att den första raden, <b>rad <- getLine</b> tolkas som även varande den sista. Kolla över det! Använd inte tabulator, utan använd mellanslag. Jag kör visserligen inte med tabbar, men det där förklarade en del. Nu ska vi se om jag får ordning på det. "Instruktioner" i Haskell?
Jag sitter och lär mig Haskell, men har fastnat lite på bland annat instruktioner.
Vad fan är en instruktion?
Vad jag förstår kan man returnera funktioner precis som vad som helst annat. Sen tillkommer instruktioner som är en slags "mall" för hur man gör något?
Och enda sättet att köra en instruktion är att använda do?
Och hur funkar det överhuvudtaget?
PS. Vet att det blev lite skumt forumval, men var passar det annars in?Sv: "Instruktioner" i Haskell?
Jag höll på lite med Common Lisp i våras, vi läste 6p här. Om jag inte minns fel så är väl Haskell och Lisp ganska lika.
Tyvärr har jag inte hört talas om "instruktioner" i Lisp, men den första tanke som dyker upp när jag läser ditt inlägg är att det motsvarar mapcar i Lisp. Mapcar fungerar så att det tar en länkad lista och en funktion som argument och applicerar funktionen på varje element i listan. Men när jag tänker efter lite mer så känns det inte som det borde heta "instruktion"...
/DanSv: "Instruktioner" i Haskell?
En monad <b>m</b> innehåller i princip två funktioner:
<b>return</b> :: a -> m a
<b>>>=</b> :: m a -> (a -> m b) -> m b
<b>return</b> kan tolkas som att den paketerar ett värde av någon typ a i ett "monadobjekt". Jämför med en konstruktor i oop.
<b>>>=</b> kan kallas sekvenskonstruktor; den tar ett monadobjekt och en funktion som utifrån det paketerade värdet skapar ett nytt monadobjekt. Resultatet är ett nytt monadobjekt.
Ett par exempel från monaden IO är
getLine :: IO String
putStrLn :: String -> IO ()
Ett program som läser en rad och skriver ut den två gånger kan skrivas så här:
<code>
getLine >>= (\rad ->
putStrLn rad >>= (\dummy ->
putStrLn rad))
</code>
Variabeln rad kommer här att vara av typen String.
För att förenkla användningen av monader och för att man skall se likheten med vanlig imperativ programmering, har do-konstruktionen utvecklats. Ovanstående program kan där skrivas
<code>
do rad <- getLine
putStrLn rad
putStrLn rad
</code>
Varför behövs då monader? Jo, i ren funktionell programmering får funktioner inte ha några sidoeffekter som de kan ha i imperativa språk. Därför måste hanteringen av sidoeffekter hanteras i en "skyddad" miljö från vilken värdena inte kan läcka ut. Och som synes ovan finns en paketingsfunktion (konstruktor), men ingen uppaketeringsfunktion ("getter" i oop). Har ett värde väl paketerats kan man inte få ut det.
Ett fullständigt program i Haskell, ett som kan kompileras för att köras fristående, har ett objekt som heter <b>main</b> och som är av typen IO a för någon typ a.
<code>
main = do rad <- getLine
putStrLn rad
putStrLn rad
</code>
Detta objekt "körs" och kan alltså jämföras med main i C m.fl. språk. Inne i monadkoden kan "vanliga" funktioner anropas:
<code>
main = do rad <- getLine
putStrLn (rad ++ "\n" ++ rad)
</code>
Här är <b>++</b> konkateneringsoperatorn som tar två listor (t.ex. två strängar) och sammanfogar dem.
Det känns som jag inte riktigt vet hur jag skall avsluta denna utläggning, så jag väljer nu att avbryta med denna punkt:.Sv:"Instruktioner" i Haskell?
Per: Tackar för den lektionen. Tyvärr verkar mitt hugs vara lite lätt korkat just nu.
Jag får nämligen inte
<code>
main = do rad <- getLine
putStrLn rad
putStrLn rad
</code>
att fungera. Den klagar på att "last argument in do {...} must be an expression" !?
Jag hade nog förstått det mesta rätt, men det är ändå lite svårt att greppa dessa instruktioner...Sv: "Instruktioner" i Haskell?
Du kan även lägga in ett radbyte efter <b>do</b>:
<code>
main = do
rad <- getLine
putStrLn rad
putStrLn rad
</code>
Ett annat sätt att skriva det på är
<code>main = do { rad <- getLine; putStrLn rad; putStrLn rad; }</code>
Haskell omvandlar den förra syntaxen till den senare utifrån vilka indrag som har gjorts.Sv:"Instruktioner" i Haskell?
Tack igen!