Haskell - Putting out result of function

  • (4 Pages)
  • +
  • 1
  • 2
  • 3
  • 4

46 Replies - 4699 Views - Last Post: 24 July 2016 - 11:47 AM

#16 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 12 July 2016 - 10:40 AM

View PostO, on 12 July 2016 - 07:18 PM, said:

This code:
 main = do
    let x = "d"
    let lst = ["a", "b", "c", x]
    lst ++ ["e"]
    putStr $ show lst



You can't have a non-monadic expression in the middle of a do block. You need to read up on how do and monads work.

Also note that lst ++ ["e"] simply produces a new list with the given elements. It does not affect the value of lst in any way. You want putStr $ show $ lst ++ ["e"] or print $ lst ++ ["e"].

Quote

And why is func not a function? I use do? When you do something, you're functioning, not?


All that do does in your definition of func is that it allows you to write let without in. Your definition is completely equivalent to:

func =
  let x = "d" in
  let lst = ["a", "b", "c", x] in
  lst ++ ["e"]



or even just:

func = ["a", "b", "c", "d", "e"]



And I'm sure you'd agree that the latter at least is no function.

Quote

Or ain't it a function because it has no parameters?


Yes.

PS: Note that do-notation is meant to be used for monads, so your usage of it in func is technically illegal, though GHC allows it.

PPS: Preprending with : is O(1) while appending with ++ is O(n), so generally you should prefer the former over the latter when generating a list.
Was This Post Helpful? 1
  • +
  • -

#17 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 12 July 2016 - 12:34 PM

Thanks a lot.
So if I understand it right, when you have something like 'func' (a declaration?), you must rather look to the result of that declaration instead of what is happening in it?

I read up a page about monads. And understood it is to 'shorten' a code? And to make something simple but too long, short but complex?
Was This Post Helpful? 0
  • +
  • -

#18 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 12 July 2016 - 01:08 PM

View PostO, on 12 July 2016 - 09:34 PM, said:

I read up a page about monads. And understood it is to 'shorten' a code? And to make something simple but too long, short but complex?


Not really, no. Monad is a common interface (type class) for types that support certain operations. Namely >>=, >> and return. Any type that implements this type class can be used with do notation (which is simply a shortcut for >>= and >>). IO is such a type. In fact the only way to interact with an IO value is through monad operations (i.e. >> and >>= or the equivalent do notation).

This should be explained in the IO section of any decent Haskell book or tutorial.
Was This Post Helpful? 1
  • +
  • -

#19 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 13 July 2016 - 06:08 AM

Okay, everything is getting a bit more clear.

Also, with Maybe. I understand it's concept and use. That if a specific 'variable' has a value, it is 'not valid', NULL, or Nothing.

And I'm able to use it with specific integers.
But what about using it with a list?
That if a specific value exists in a list, it ain't valid or Nothing.

myList = do
    let x = "d"
    let lst = ["a", "b", "c", x]
    lst ++ ["e"]

--Testing 'Maybe'
excludedList = [1..10]
f::Int -> Maybe Int
f excludedList = Nothing
f x = Just x



main = do
    putStrLn $ show myList
    putStrLn $ show $ f 15

    let anotherList = ["a", "b", "c", "d"]
    putStr $ unlines anotherList
    mapM putStr anotherList

    putStrLn "\n\n\n\n\n"

    putStr $ unlines myList




Output (compiles fine, but warning):

Quote

Pattern match is redundant
In an equation for `f': f x = ...


Also, the parameter of f is 15, so should 'return' 15. But it's returning 'Nothing', but 15 ain't in the excludedList.

This post has been edited by O'Niel: 13 July 2016 - 06:10 AM

Was This Post Helpful? 0
  • +
  • -

#20 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 13 July 2016 - 10:38 AM

View PostO, on 13 July 2016 - 03:08 PM, said:

--Testing 'Maybe'
excludedList = [1..10]
f::Int -> Maybe Int
f excludedList = Nothing
f x = Just x



In your first line excludeList is just the name of your parameter. It has no connection to the global variable of the same name. What you want is:

f x | x `elem` excludeList = Nothing
f x = Just x



or:

f x =
  if x `elem` excludeList
  then Nothing
  else Just x



elem is the function used to find whether a given value is an element of the given list. The | syntax allows you to say "this case of the function definition should only be used if the given condition applies. It can be used as an alternative to if-statements in cases like this.
Was This Post Helpful? 1
  • +
  • -

#21 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 14 July 2016 - 04:52 PM

Hi!
Thanks again.

Now I'm trying to create some basic list-functions and for the replace function I need the Lens-package. I tried import Control.Lens, but that gives this error:

Quote

Could not find module `Control.Lens'
It is not a module in the current program, or in any known package.


Code:
import Control.Lens

myList = do
    let x = "d"
    let lst = ["a", "b", "c", x]
    lst ++ ["e"]

excludedList = [1..10]
f::Int -> Maybe Int
f x =
    if x `elem` excludedList
        then Nothing
    else Just x

--------------------
deleteAtIndex :: Int -> [a] -> [a]
deleteAtIndex i lst = do
    let z = splitAt (i + 1) lst
        x = init $ fst z
        y = snd z

    x ++ y

insertAtIndex :: Int -> [a] -> [a] -> [a]
insertAtIndex i lst s = do
    let z = splitAt (i + 1) lst
        x = (fst z) ++ s
        y = snd z
    
    x ++ y

replaceAtIndex :: Int -> [a] -> Int -> [a]
replaceAtIndex i lst newNmr = do
    lst & i .~ newNmr

main = do
    putStrLn $ show myList
    putStrLn $ show $ f 15

    let anotherList = ["a", "b", "c", "d"]
    putStr $ unlines anotherList
    mapM putStr anotherList

    putStrLn "\n\n\n\n\n"

    putStr $ unlines myList

    putStrLn "\n\n\n\n\n"

    let testLst1 = [1..25]
    putStrLn $ show $ deleteAtIndex 10 testLst1
    putStrLn $ show $ insertAtIndex 15 testLst1 [12345]
    putStrLn $ show $ replaceAtIndex 7 testLst1 99



Was This Post Helpful? 0
  • +
  • -

#22 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 15 July 2016 - 06:25 AM

lens is a library that you need to install before you can use it.

replaceAtIndex :: Int -> [a] -> Int -> [a]


Those types don't work out. You can't insert an Int into a list of as. The inserted element should also have type a.

PS: Note that random access for Haskell lists is O(n), so you don't really want to use them like this in real applications.
Was This Post Helpful? 0
  • +
  • -

#23 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 15 July 2016 - 12:45 PM

In ReplaceIndex, why ain't the second working, but the first perfectly?

To replace a specific element in a list I want to do the following:
1) Take the index of the element I want to replace
2) Delete the element at that index
3) and then adding the new chosen element at that index.

import Data.List

myList = do
    let x = "d"
    let lst = ["a", "b", "c", x]
    lst ++ ["e"]

excludedList = [1..10]
f::Int -> Maybe Int
f x =
    if x `elem` excludedList
        then Nothing
    else Just x

deleteAtIndex :: Int -> [a] -> [a]
deleteAtIndex i lst = do
    let z = splitAt (i + 1) lst
        x = init $ fst z
        y = snd z

    x ++ y

insertAtIndex :: Int -> [a] -> [a] -> [a]
insertAtIndex i lst s = do
    let z = splitAt (i + 1) lst
        x = (fst z) ++ s
        y = snd z
    
    x ++ y

------------------------------------------------
replaceAtIndex :: Int -> [a] -> [a] -> Maybe Int
replaceAtIndex toReplace lst newNmr = do
	--works
	elemIndex 2 [1,2,3,4,5,6,7,8,9]
	--works not
	elemIndex toReplace lst	


main = do
    putStrLn $ show myList
    putStrLn $ show $ f 15

    let anotherList = ["a", "b", "c", "d"]
    putStr $ unlines anotherList
    mapM putStr anotherList

    putStrLn "\n\n\n\n\n"

    putStr $ unlines myList

    putStrLn "\n\n\n\n\n"

    let testLst1 = [1..25]
    putStrLn $ show $ deleteAtIndex 10 testLst1
    putStrLn $ show $ insertAtIndex 15 testLst1 [12345]
    putStrLn $ show $ replaceAtIndex 5 testLst1 [3]



This post has been edited by andrewsw: 15 July 2016 - 01:31 PM
Reason for edit:: Removed previous quote, just press REPLY

Was This Post Helpful? 0
  • +
  • -

#24 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 15 July 2016 - 12:54 PM

elemIndex requires the elements of the list to have a type that implements the Eq type class (which allows values to be compared for equality). However you accept a list of any type a, so it may or may not implement Eq. To fix this simply add Eq a => to the beginning of your type signature, which says that the function only works for types a that implement Eq.
Was This Post Helpful? 1
  • +
  • -

#25 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 15 July 2016 - 01:43 PM

I tried that, and also tried to give the signature of elemIndex where it's declared.
But I got this error in place:

Quote

* Couldn't match type `a' with `Int'
`a' is a rigid type variable bound by
the type signature for:
replaceAtIndex :: forall a. Eq a => Int -> [a] -> [a] -> Maybe Int
at C:\users\niel\desktop\test2.hs:32:19
Expected type: [Int]
Actual type: [a]
* In the second argument of `elemIndex', namely `lst'
In a stmt of a 'do' block: elemIndex toReplace lst
In the expression:
do { elemIndex 2 [1, 2, ....];
elemIndex toReplace lst }
* Relevant bindings include
newNmr :: [a] (bound at C:\users\niel\desktop\test2.hs:33:30)
lst :: [a] (bound at C:\users\niel\desktop\test2.hs:33:26)
replaceAtIndex :: Int -> [a] -> [a] -> Maybe Int
(bound at C:\users\niel\desktop\test2.hs:33:1)



Code:
import Data.List

myList = do
    let x = "d"
    let lst = ["a", "b", "c", x]
    lst ++ ["e"]

excludedList = [1..10]
f::Int -> Maybe Int
f x =
    if x `elem` excludedList
        then Nothing
    else Just x

deleteAtIndex :: Int -> [a] -> [a]
deleteAtIndex i lst = do
    let z = splitAt (i + 1) lst
        x = init $ fst z
        y = snd z

    x ++ y

insertAtIndex :: Int -> [a] -> [a] -> [a]
insertAtIndex i lst s = do
    let z = splitAt (i + 1) lst
        x = (fst z) ++ s
        y = snd z
    
    x ++ y

------------------------------------------------
replaceAtIndex :: Eq a => Int -> [a] -> [a] -> Maybe Int
replaceAtIndex toReplace lst newNmr = do 
	--works
	elemIndex 2 [1,2,3,4,5,6,7,8,9]
	--works not
	elemIndex toReplace lst	


main = do
    putStrLn $ show myList
    putStrLn $ show $ f 15

    let anotherList = ["a", "b", "c", "d"]
    putStr $ unlines anotherList
    mapM putStr anotherList

    putStrLn "\n\n\n\n\n"

    putStr $ unlines myList

    putStrLn "\n\n\n\n\n"

    let testLst1 = [1..25]
    putStrLn $ show $ deleteAtIndex 10 testLst1
    putStrLn $ show $ insertAtIndex 15 testLst1 [12345]
    putStrLn $ show $ replaceAtIndex 5 testLst1 [3]




However, toReplace is an Int, and lst a List ([a]), just like elemIndex should be?
Was This Post Helpful? 0
  • +
  • -

#26 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 16 July 2016 - 06:03 AM

elemIndex gives you the index of a given element. So when you call elemIndex toReplace lst it searches for the element toReplace in the list lst. This means that if lst is a list of as, toReplace must be an a.
Was This Post Helpful? 1
  • +
  • -

#27 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 16 July 2016 - 06:55 AM

Thanks a lot!
It's working now. You're a damn Haskell-wizard. ;)

And this is because the `a` represents the `a` in [a].
And when you define the type-definition, `a` stands for whatever type [a] holds?
Was This Post Helpful? 0
  • +
  • -

#28 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 16 July 2016 - 07:17 AM

Right, in a type signature a lower case identifier (or rather one starting with a lower case letter) can stand for any type and if the same identifier occurs multiple times in the same signature, it stands for the same type each time. So a -> [a] can be used as Int -> [Int] or String -> [String], but not Int -> [String] or String -> [Int], whereas a -> [b] can be used as all four.
Was This Post Helpful? 1
  • +
  • -

#29 O'Niel  Icon User is offline

  • D.I.C Regular

Reputation: 14
  • View blog
  • Posts: 389
  • Joined: 13-September 15

Re: Haskell - Putting out result of function

Posted 16 July 2016 - 07:27 AM

So, I finished my 'algorithm' but I encountered the problem that I have to convert Maybe Int to Int, to use the splitAt-function.
I tried fromJust, but this wasn't working and disadvised. I also tried 'read' but that's rather for string to int I guess.

So now I cam up with using a Maybe-case.

Code:
import Data.List
import Data.Maybe

myList = do
    let x = "d"
    let lst = ["a", "b", "c", x]
    lst ++ ["e"]

excludedList = [1..10]
f::Int -> Maybe Int
f x =
    if x `elem` excludedList
        then Nothing
    else Just x

deleteAtIndex :: Int -> [a] -> [a]
deleteAtIndex i lst = do
    let z = splitAt (i + 1) lst
        x = init $ fst z
        y = snd z

    x ++ y

insertAtIndex :: Int -> [a] -> [a] -> [a]
insertAtIndex i lst s = do
    let z = splitAt (i + 1) lst
       	x = (fst z) ++ s
        y = snd z
    
    x ++ y

------------------------------------------------
replaceAtIndex :: Eq a => a -> [a] -> [a] -> Maybe Int
replaceAtIndex toReplace lst newNmr = do
    let i = elemIndex toReplace lst
	    
    case i of
        Just i ->
            let z = splitAt i lst
                x = fst z
                y = snd z
        Nothing 
    
    init $ fst x
    x ++ newNmr
    x ++ y


main = do
    putStrLn $ show myList
    putStrLn $ show $ f 15

    let anotherList = ["a", "b", "c", "d"]
    putStr $ unlines anotherList
    mapM putStr anotherList

    putStrLn "\n\n\n\n\n"

    putStr $ unlines myList

    putStrLn "\n\n\n\n\n"

    let testLst1 = [1..25]
    putStrLn $ show $ deleteAtIndex 10 testLst1
    putStrLn $ show $ insertAtIndex 15 testLst1 [12345]
    putStrLn $ show $ replaceAtIndex 5 testLst1 [3]




Error:

Quote

42:9 parse error (possibly incorrect indentation or mismatched brackets)


However, when I put 'Nothing' on the same height as where x & y are declared, I get that same error on line 44. All my whitespaces are on the same height, and I'm only using spaces (expandtab in Vim).

I also tried, Nothing -> puStr "Nothing found!", but got the error:

Quote

Parse error on ->
.

This post has been edited by O'Niel: 16 July 2016 - 07:28 AM

Was This Post Helpful? 0
  • +
  • -

#30 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: Haskell - Putting out result of function

Posted 16 July 2016 - 08:01 AM

All patterns should be on the same height and be followed by -> and an expression. Your problem is that your let-expression wasn't finished. The syntax is let <bindings> in <expression> and you're missing the in <expression> part.

Also all cases need to be the same type and you can't use putStr outside of the IO monad. So your Nothing case should probably just be Nothing -> Nothing.

Also note that any statement in a do-body should be an expression of the same monadic type. In your code the case expression evaluates to a Maybe (or it will once the first case is fixed to evaluate at all), but then the following expressions evaluate to lists, which are a different monad. You can't mix monads like that.

You also still seem to think of the semantics in terms of side-effects, which is wrong. An expression like x ++ newNmr won't do anything unless you use its result. Sure, if you're in the list monad you can write

do
  x ++ newNmr
  foo



to basically duplicate the elements in foo, but usually you want to use its value, not just its length. And either way it's definitely not what you want here (especially since you aren't even in the list monad).

For now I'd recommend not using do-notation outside of IO-functions at all until you've understood how monads work and what the given types semantics are when used as a monad.
Was This Post Helpful? 0
  • +
  • -

  • (4 Pages)
  • +
  • 1
  • 2
  • 3
  • 4