F# type constraints indexable - indexing

I'm trying to make a type that should represent a "slice" of some indexable collection.
I know that there are some similar types in F# but not one that specifies the criteria that I need.
To do this it needs to carry a reference to the collection of type 'content and the content needs to be indexable. So I tried this constraint since a type only needs to have the member Item (get/set) so I tried this
type Slice<'a, 'content when 'content: (member Item: int -> 'a)>
This still throw the usual error
So is it possible to constrain a type to still be generic but constraint to be indexable?

I think something like this should work:
type Slice<'a, 'content when 'content: (member get_Item: int -> 'a)> =
{
Content : 'content
Start : int
Stop : int
}
with
member inline slice.get_Item(i) =
slice.Content.get_Item(slice.Start + i)
I've implemented get_Item on Slice as well, so you can take a slice of a slice. Here are some values of this type:
let strSlice =
{
Content = "hello"
Start = 1
Stop = 2
}
let arraySlice =
{
Content = [| 2; 4; 6; 8 |]
Start = 0
Stop = 3
}
let strSliceSlice =
{
Content = strSlice
Start = 0
Stop = 1
}

[<Interface>]
type Indexable<'a> =
abstract member Item: int -> 'a with get
[<Struct>]
type Slice<'a> =
{
content: Indexable<'a>
start: int
len: int
}
with
interface Indexable<'a> with
member I.Item with get(i) = I.[idx]
member S.Item with get(idx) =
if idx >= S.len
then raise(IndexOutOfRangeException())
else S.content.[S.start+idx]
This works.

Related

can't get Kotlin to check if variable in listOf

I've tried this 10 different ways and i can't get this to work.
I want this Kotlin code to take in a string, check each character of that string against a listOf characters, and, if it is in that list, increase a counting variable by 1, so then at the end it can check if that counting variable is high enough to pass a test. this is taken straight from Sololearn: Code Coach - Password Validator. I have completed this code successfully already in Python (https://code.sololearn.com/c0fl17IMHPfC), but in trying to convert it over to Kotlin, it doesn't seem to work. The variables don't seem to register as true when compared to the elements in the listOf.
fun main() {
var password: String = readLine()!!
var numberCount: Int = 0
var numbers: List<String> = listOf("0","1","2","3","4","5","6","7","8","9")
var specialCount: Int = 0
var specialCharacters: List<String> = listOf("!","#","#","$","%","&","*")
if (password.length < 7) {
println("Weak")
} else {
for (character in password) {
println(character)
var numberCheck = numbers.contains(character)
println(numberCheck)
if (numberCheck == true) {
numberCount += 1
}
var specialCharactersCheck = specialCharacters.contains(character)
println(specialCharactersCheck)
if (specialCharactersCheck == true) {
specialCount += 1
}
}
println(numberCount)
println(specialCount)
if (numberCount < 2) {
println("Weak")
} else if (specialCount < 2) {
println("Weak")
} else {
println("Strong")
}
}
}
When I enter an input of "letssee43$#", the result of this code is:
l
false
false
e
false
false
t
false
false
s
false
false
s
false
false
e
false
false
e
false
false
4
false
false
3
false
false
$
false
false
false
false
0
0
Weak
Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.
Your list is a list of Strings, but for (character in password) loops over the Chars in password. So you're trying to see if one of the Strings in your list is a specific Char, which it isn't, because they're two different types - a string with a single character in it is still a String, not a Char (that's why you're getting that type error)
There are lots of ways to do it (and there's nothing wrong with your code besides the Char/String thing!), personally I'd just do this:
var numbers = "0123456789"
var specialCharacters = "!##$%&*"
val password = "letssee43$#"
val nums = password.count { it in numbers }
val specials = password.count { it in specialCharacters }
println("nums: $nums, specials: $specials")
> nums: 2, specials: 2
count is iterating over the Chars in password and counting how many of them each character string contains. A String is treated like an array of Chars, so you can check it that way. (You could also add .toList() after the string declaration if you really want your characters stored in a list - that way it'll be a List<Char> so the lookup will still work.)
Or you could do things the way you are, and explicitly write out the listOf elements - but make them Chars instead, e.g. listOf('1') (single quotes) instead of listOf("1") (double quotes).
If you do want to search a list of strings for a match, you need to provide a String, so you need to convert your Char to one, e.g. by calling toString() on it, using a literal like "$character", etc.
edit like gidds points out below, sets are way more efficient for lookups like in or contains, so toSet() is a better idea than toList() unless you really need that ordered list for some reason. If you don't care about efficiency (like if you're not doing a lot of lookups) I'd personally just leave it as a string like in the code block up there - it's nice and simple. But if you do want to be more efficient, or if you do need a collection (like if you're matching against Strings) then a Set is ideal
I will give you another way to get the same result as you by using Extensions
fun main() {
var password: String = readln()
println("Password contain numbers amount: " + password.containNumbersAmount())
println("Password contain special characters amount: "+ password.containSpecialCharactersAmount())
println("Password Status : "+ password.validationResult())
}
fun String.containNumbersAmount() = count { it.isDigit() }
fun String.containSpecialCharactersAmount(): Int {
val specialCharacters = "!##$%&*"
return count { it in specialCharacters } }
fun String.validationResult() : String {
return when {
length < 7 -> "Weak"
containNumbersAmount() < 2 -> "Weak"
containSpecialCharactersAmount() < 2 -> "Weak"
else -> "Strong"
}
}
The problem is that your Lists contain Strings, so every time you call contains on them and pass a Char, it will always be false because a Char is not a String.
Probably, the best way to fix it is to declare Iterables of Chars to check them. Lists are Iterables, but so are ranges.
val password: String = readln()
var numberCount: Int = 0
val numbers: Iterable<Char> = '0'..'9'
var specialCount: Int = 0
val specialCharacters: List<Char> = listOf('!','#','#','$','%','&','*')
And just for your learning, there's a count function that takes a lambda argument that can make this kind of task much easier:
fun main() {
val password: String = readln()
val numbers = '0'..'9'
val specialCharacters = listOf('!','#','#','$','%','&','*')
val numberCount: Int = password.count { numbers.contains(it) }
val specialCount: Int = password.count { specialCharacters.contains(it) }
val result = when {
password.length < 7 || numberCount < 2 || specialCount < 2 -> "Weak"
else -> "Strong"
}
println(result)
}

Extract value out of Kotlin arrow Either type and assign it to const

It would be a basic question, but I couldn't figure out a solution. I need to initialize a constant out of the right-side value of below either type.
val test: Either<String, Int> = 1.right()
I tried something like below but it shrinks the scope of the constant.
when(test) {
is Either.Right -> {val get:Int = test.b}
is Either.Left -> println(test.a)
}
I want that get to be scoped outside of when statement. Is there any way to do it or Arrow Either is not made for this purpose?
The important question is: what should happen if the Either is Left. In this example it is created close to where it's used, so it is obvious to you as a developer. But to the compiler what is inside the Either can be either an Int or a String.
You can extract the value using for example fold:
val x = test.fold({ 0 }, {it}) // provide 0 as default in case the Either was a `Left`
// x = 1
another option is getOrElse
val test = 1.right()
val x = test.getOrElse { 42 } // again, default in case it was a `Left`
// x = 42
You can also work with it without unwrapping it:
val test = 1.right()
val testPlus10 = test.map { it + 10 } // adds 10 to `test` if it is `Right`, does nothing otherwise
val x = testPlus10.getOrElse { 0 } // unwrap by providing a default value
// x = 11
For more example check the official docs.
Recommended reading: How do I get the value out of my Monad

postings nextPosition returns nul, freq returns 0, payload() returns null

I made simplest index with one document using LuceneTestCase. My goal is to write numbers to payload for each position of each term, that will be used in custom scoring formula implemented in custom Query/Scorer.
I used SimpleTextCodec and checked, that freq, positions and payload was really written to index.
But when I'm reading freq from the PostingEnum it returns 0, payload() returns null, nextPosition() throws an exception:
java.lang.AssertionError: got line=field model
at __randomizedtesting.SeedInfo.seed([D334C9D1B5C155E3:2AAE4BE5481F4C8F]:0)
at
org.apache.lucene.codecs.simpletext.SimpleTextFieldsReader$SimpleTextPostings Enum.nextPosition(SimpleTextFieldsReader.java:455)
Here is how I'm reading the postings in the custom Query:
for (String field: fieldScores.keySet()) {
final Terms fieldTerms = reader.terms(field);
if (fieldTerms == null) {
continue;
}
if (!fieldTerms.hasPositions())
throw new IllegalStateException("Index does not contain positions");
if (!fieldTerms.hasPayloads())
throw new IllegalStateException("Index does not contain payloads");
final TermsEnum te = fieldTerms.iterator();
for (int j = 0; j < terms.length; j++) {
final Term t = terms[j];
if (t.field().equals(field) && te.seekExact(t.bytes())) {
PostingsEnum postingsEnum = te.postings(null, PostingsEnum.ALL);
int pos = postingsEnum.nextPosition();
BytesRef payload = postingsEnum.getPayload();
// assert payload.bytesEquals(new BytesRef(new byte[]{1}));
// TODO: use payload in scoring formula
fldScorers.add(new ConstTermScorer(this, t,
fieldScores.get(field) * termScores.get(t.text()),
postingsEnum));
}
}
}
I've found the reason. nextPosition(), freq() and payload() return 0 (or null) values because postingsEnum (iterator) is just created and not positioned on concrete document yet. postingsEnum.nextDoc() wasn't called and postingsEnum.docID() is -1. Stupid situation, but it would be better may be if nextPosition(), freq() and payload() would check postingsEnum.docID.

Elm: How does this init work?

type alias Model =
{ dieFace : Int
}
init : (Model, Cmd Msg)
init =
(Model 1, Cmd.none)
Why does the integer 1 get passed to the model ala Model 1?
The type alias seems to requiring a record?
There is not so much un-explained magic in Elm (for good reason), but one bit is the type and type alias constructors. Whenever you create a type (alias) you get a constructor function for free. So, to use your example,
type alias Model =
{ dieFace : Int
}
gives you a (somewhat weird-looking) constructor function
Model : Int -> Model
for free. If you add more entries to your record, like this
type alias Model =
{ dieFace : Int
, somethingElse : String
}
the constructor function takes more arguments.
Model : Int -> String -> Model
The order of these are the same order as the record entries, so if you change the order of your type aliases, you'll have to change the argument order to to the constructor function.
Union types work in a similar way.
type Shape
= Circle Int
| Square Int Int
quietly creates constructors:
Circle: Int -> Shape
Square : Int -> Int -> Shape
In Model 1 "Model" is used as positional record constructor. It is equal to {dieFace = 1}
Here is another example:
type alias Rcd =
{ first : String
, second : Int
}
Rcd can be constructed in two ways:
Rcd "some string" 4
{ first = "some string" , second = 4}
The former variant is just shorthand and often used for initialisation of Records.

Encoding vector length field not adjacent to the vector

I have the following structure I like to encode.
I'm aware that I can encode a vector with vector() if the size field is directly in front of the vector data. But here the field encoding the vector size is not adjacent.
case class Item(
address: Int,
size: Int,
)
case class Header {
// lots of other fields before
numOfItems: Int,
// lots of other fields after
}
case class Outer(
hdr: Header,
items: Vector[]
)
Decoding of Outer is OK:
Header.numOfItems is read from the bit vector and items is created with vectorOfN(provide(hdr.numOfItems, Item.codec))
Encoding of Outer is the problem:
When encoding I would like to have numOfItem be taken from the items.length.
I'm aware that I could set numOfItems with additional code when the items Vector is updated or with something like a "before encoding callback".
The question is if there is a more elegant solution. To me Header.numOfItems is redundant with Outer.items.length, so ideally only the
Encoder should know about numOfItems.
You could try building a Codec using consume() and start without building the Outer object:
case class OuterExpanded(
fieldBefore: Int, // Field before number of items in the binary encoding
fieldAdter: Int, // Field after number of items in the binary encoding
items: Vector[Item] // Encoded items
)
// Single Item codec
def itemC: Codec[Item] = (int32 :: int32).as[Item]
def outerExpandedC: Codec[OuterExpanded] = (
int32 :: // Field before count
int32.consume( c => // Item count
int32 :: // Field after count
vectorOfN(provide(c), itemC)) // 'consume' (use and forget) the count
(_.tail.head.length) // provide the length when encoding
).as[OuterExpanded]
As defined above, you get the following when encoding: outerExpandedC.encode(OuterExpanded(-1, -1, Vector(Item(1,2), Item(3,4)))) returns
Successful(BitVector(224 bits,
0xffffffff00000002fffffffe00000001000000020000000300000004))
^ ^ ^ ^-------^-> First Item
|-1 | |-2
|Vector length inserted between the two header fields
Afterwards, you can xmap() the Codec[OuterExpanded] to pack the other header fields together into their own object. Ie (adding two conversion methods to Outer and OuterExpanded):
def outerC: Codec[Outer] =
outerExpandedC.xmap(_.toOuter,_.expand)
case class OuterExpanded(fieldBefore: Int, fieldAfter: Int, items: Vector[Item]) {
def toOuter = Outer(Hdr(fieldBefore,fieldAfter), items)
}
case class Outer(header: Hdr, items: Vector[Item]) {
def expand = OuterExpanded(header.beforeField1, header.beforeField1, items)
}
This can probably be adapted to more complex cases, though I'm not entirely familar with shapeless' heterogeneous lists – or HList – and there might be nicer ways to get to the length of the vector rather than calling _.tail.head.length in the example above, especially if you end up with more than one field after the number of encoded values.
Also, the Codec scaladoc is a nice place to discover useful operators
Based on the previous answer I came up with something like the code below.
I used the consume trick form above and an AtomicInteger to hold the size of the vector.
import java.util.concurrent.atomic.AtomicInteger
import scala.Vector
import org.scalatest._
import scodec._
import scodec.Attempt._
import scodec.codecs._
import scodec.bits._
object SomeStructure {
case class Item(
address: Int,
size: Int)
def itemC: Codec[Item] = (int32 :: int32).as[Item]
case class Hdr(
beforeField1: Int,
// vectorSize would be here
afterField1: Int)
// vectorSize is an "in" param when encoding and an "out" param when decoding
def hdrC(vectorSize: AtomicInteger): Codec[Hdr] =
(int32 ::
int32.consume(c => {
vectorSize.set(c);
int32
})((i) => vectorSize.get)).as[Hdr]
case class Outer(
hdr: Hdr,
var items: Vector[Item])
def outerC() = {
// when decoding the length is in this atomic integer
// when encoding it is set before
val c = new AtomicInteger(-1)
(hdrC(c) :: lazily(vectorOfN(provide(c.get), itemC)))
.xmapc(identity)((g) => { c.set(g.tail.head.length); g })
}.as[Outer]
}
import SomeStructure._
class SomeStructureSpec extends FlatSpec with Matchers {
val bv = hex"ffffffff00000002ffffffff00000001000000020000000300000004".bits
val v = Vector(Item(1, 2), Item(3, 4))
val bv2 = hex"ffffffff00000003ffffffff000000010000000200000003000000040000000500000006".bits
val v2 = Vector(Item(1, 2), Item(3, 4), Item(5, 6))
val o = Outer(Hdr(-1, -1), v)
"outerC" should "encode" in {
o.items = v
outerC.encode(o) shouldBe Successful(bv)
o.items = v2
outerC.encode(o) shouldBe Successful(bv2)
}
it should "decode" in {
o.items = v
outerC.decode(bv) shouldBe Successful(DecodeResult(o, BitVector.empty))
o.items = v2
outerC.decode(bv2) shouldBe Successful(DecodeResult(o, BitVector.empty))
}
}