Haskell As-patterns, binding variables to constants - haskell

(This code doesn't make much sense, but I need this logic to work in my other complicated function):
import Data.List
elemIndex1 xss#(x:xs) =
if (x == ' ')
then (elemIndex x xss)
else (elemIndex1 xs)
So I want this function to give this:
elemIndex1 "qwe asd zxc"
Just 3
Instead it gives this:
elemIndex1 "qwe asd zxc"
Just 0
As I understand, at the else clause xss actually becomes xs.
So my question is: is there a possibility to bind the variable (x:xs) to a constant and to use this constant at any iteration?

It seems like you are expecting xss#(x:xs) to be the following:
xss: the original string given to elemIndex1
x: the first character of an arbitrary call
xs: the rest of the characters of an arbitrary call
e.g. for your example when x first matches a space
xss = "qwe asd zxc"
x = ' '
xs = "asd zxe"
This is not how the pattern match works. xss is actually equal to x:xs, so in that example it would be " asd zxc".
If you want to keep around the first call to a function, you can use a helper function called inside of the scope of the original function.
weirdElemIndex str = weirdElemIndex' str
where
weirdElemIndex' "" = Nothing
weirdElemIndex' (x:xs) =
if x == ' '
then elemIndex ' ' str
else weirdElemIndex' xs
Note that the str I reference in the body of the helper function will be a constant in its invocation.
For what it’s worth, your contrived example seems to be equivalent to elemIndex ' ' since it deals with the case where there is no space in the string by returning Nothing.

Related

list vs. incremental values security

Can someone tell me the formal reason why list/arrays and such are considered more secure when it comes to incremental steps i.e (List.fold > loops).
Exampel code in F#
Functional way (list)
let rec sum lst =
match lst with
| [] -> 0
| x::xs -> x + sum xs
Imperative way (incremental)
let sum n m =
let mutable s = 0
for i=n to m do
s <- s + i
s
If by security you mean "safer" -- then I think this will explain it some. To begin with if you're summing a list, a fold should be somewhat safer as it removes the need for the programmer to correctly index the list:
let sum lst =
let mutable s = 0
for i=0 to (List.length lst - 1) do
s <- s + lst.[i]
s
You avoid a lot of pitfalls completely by using the library function:
let sum lst =
let folder acc element =
acc + element
List.fold folder 0 lst
The fold handles all the edge cases for you, in terms of indices, and list length. (note: this could also be done with a List.reduce (+) lst however that does not handle an empty list, where as a fold does).
The short of it all is that it keeps the programmer from making mistakes on silly index math, and keeps the focus on the actual logic of what is being done.
EDIT: I ironically messed up the index logic in my initial post

SML - Find element in a list and substitute it

I'm trying to build a function which takes as input two list of type
(string*string) list
and returns one list of the same type. The first list is like a "lookup" list in which the second element is the element to search and the first element is the element to use for the substitution. The aim of the function is to find which element in the second list is equal to which element of the first list. In case of matching the element of the second list will be substitute with the correspondent element of the tuple in the first element. Below an example:
fun check([("0","s0"),("1","s0l0s1"),("2","s1"),("3","s1l1s0")],[("s0","s0l0s1"),("s0l0s1","s1"),("s1","s1l1s0"),("s1l1s0","s0")]);
With these inputs the function should return:
val it = [("0","1"),("1","2"),("2","3"),("3","0")]
Since "s0" corresponds to "0", "s0l0s1" corresponds to "1", "s1" corresponds to "2" and "s1l1s0" corresponds to "3".
I've done two functions so far:
fun check1((l1 as (x1,y1))::nil,(l2 as (x2,y2))::nil) = if x2 = y1 then [(x1,y2)] else nil
|check1((l1 as (x1,y1))::rest1,(l2 as (x2,y2))::rest2) =
if x2 = y1 then (x1,y2)::check1(rest1,rest2)
else check1(rest1,l2::rest2)
fun check2((l1 as (x1,y1))::nil,(l2 as (x2,y2))::nil) = if y2 = y1 then [(x2,x1)] else nil
|check2((l1 as (x1,y1))::rest1,(l2 as (x2,y2))::rest2) =
if y2 = y1 then (x2,x1)::check2(rest1,rest2)
else check2(rest1,l2::rest2)
The first one checks the element of the first tuple of the second list and the second function checks the element of the second tuple. But they don't work properly. Someone can help me in understanding where is the mistake?
Thanks a lot!
You're making this way too complicated.
This first function looks up a string in the first list:
fun lookup ((a,b)::xs) v = if v = b then a else lookup xs v
| lookup nil v = v;
And this one just runs recursively on both elements in the second list:
fun check (xs,((a,b)::ys)) = (lookup xs a, lookup xs b)::check(xs,ys)
| check (xs,nil) = nil;

Haskell, Length of list returning the value 1

I'm working with some code and there seems to be an issue which I can't figure out.
So I've got a method which decrements an input Int by 1 until it hits 5. (I know if i enter less than 1 it would cause an error but i will fix that later)
I have a second function which calls a takes a List as a parameter which calls this function and returns the list of numbers, I want to call length on this list and populate a separate list (I'm not the best at explaining, i'll show with code examples below)
sub 5 = return [1]
sub x =
do
xs <- sub (x - 1)
return (x:xs)
f xs = [ length (sub x) | x<-xs ]
If I call sub 10 on it's own it gives the output [10,9,8,7,6,1], however if I call length on this, it gives the output [1].
In my head i thought the output would be 6, as it has 6 elements in.
Does anyone have any idea why this is happening and/or a way to fix it?
Thanks in advance.
sub doesn't return [10,9,8,6,1] but [[10,9,8,6,1]] (a list of list) therefore the length is 1. You don't need the return. You are in a list monad, return wraps it's value into a list, this why you end up with nested list. Your code should be
sub 5 = [1] -- or return 1
sub x = do
let xs = sub (x -1)
(x:xs)
The problem is that this sub function is written like you were in an imperative language and that return doesn't mean the same thing in Haskell : it means "wrap this thing in a Monad (which Monad depends on the context)". Here since you use length on the result of sub the list [] monad is used and the result is [ [10, 9, 8, 7, 6, 5] ] a list of one element which happen to be a list of 6 elements. mb14 correctly identified that but then corrected only the first case of your function, the second case is also monadic but shouldn't be...
sub 5 = [1]
sub x = x : sub (x - 1)
is the simple code you should be using, you don't need any monad here...

Create a list from many other lists f#

First of all im VERY VERY noob in f# so I need your help :)
I have a library with 50 lists that each have around 10 entries
What I need to do is join all 50 lists into one big list. The things is that I cant use "for" or mutable variables.
what I have done (which I think is horribly done) is:
let rec finalList x =
if x < wallID.Length then List.append [interfaz.hola(wallID.Item(x)).[0].[1]] [finalList]
else listaFinal (x+1)
printfn "list %A" (listaFinal 10 )
WallID represents one of the 50 lists and interfaz.GetMuroHumano(wallID.Item(x)).[0].[1] gets me one of the entries that I need. (for now if a can just get one of the data for each wallID im ok)
again im verrrrry noob and I hope you guys can help me
thanks
EDIT:
So now its partially working..
let rec finalList x y =
if x < wallID.Length then
if y < [interfaz.GetMuroHumano(wallID.Item(x)).[y]].Length then
let current = [interfaz.GetMuroHumano(wallID.Item(x)).[y].[1]]
let rest = finalList (x y+1)
List.append current rest
else finalList (x+1 y)
else []
vut im getting errors calling the function finalList it says that "y" is not an int but a string
It is hard to say what is wrong with your code without seeing a complete version. As Daniel points out, there is a built-in library function for doing that - in fact, you do not even need List.collect, because there is List.concat that takes a list of lists.
However, you might still try to get your original code to work - this is useful for understanding functional concepts! I added some comments that can help you understand how it should work:
let rec finalList x =
if x < wallIDLength then
// Get the list at the index 'x'
let current = interfaz.GetMuroHumano(wallID.Item(x))
// Recursively process the rest of the lists
let rest = finalList (x + 1)
// Check that both 'current' and 'rest' are variables
// of type list<'T> where 'T is the element type
List.append current rest
else
// Return empty list if we got too far
[]
// Start from the first index: 0
printfn "list %A" (finalList 0)
let flatten xs = List.collect id xs

Non character argument in R string split function (strsplit)

This works
x <- "0.466:1.187:2.216:1.196"
y <- as.numeric(unlist(strsplit(x, ":")))
Values of blat$LRwAvg all look like X above but this doesn't work
for (i in 1:50){
y <- as.numeric(unlist(strsplit(blat$LRwAvg[i], "\\:")))
blat$meanLRwAvg[i]=mean(y)
}
Because of:
Error in strsplit(blat$LRwAvg[i], "\:") : non-character argument
It doesn't matter if I have one, two or null backslashes.
What's my problem? (Not generally, I mean in this special task, technically)
As agstudy implied blat$LRwAvg <- as.character(blat$LRwAvg) before loop fixed it
blat$meanLRwAvg <- blat$gtFrqAvg #or some other variable in data frame with equal length
blat$LRwAvg <- as.character(blat$LRwAvg)
for (i in 1:50){
y <- as.numeric(unlist(strsplit(blat$LRwAvg[i], "\\:")))
blat$meanLRwAvg[i]=mean(y)
}

Resources