Reputation: 478
I am trying to build my custom generic list class with fold, rightfold, leftfold and map functions. But i don't want to build using Cons constructor and i don't want to use std scala lib or inherent scala list object. Is it possible to create list object using fold right function.
As per SF Scala: Gabriel Claramunt, All about a Fold scala list using fold vs Cons https://www.youtube.com/watch?v=rdEFiMNxr0I at 22.03 in above video , he explained that fold replaces data type constructors.
Recursive aapproach:-
import scala.annotation.tailrec
sealed abstract class myList[+A] {
def head():A
def tail():myList[A]
def apply[A](as: A*): myList[A] ={
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
}
def isEmpty():Boolean ={
this match {
case Nil => true
case _: myList[A] => false
}
}
def preappend[B>:A](x: B): myList[B] ={
if (isEmpty) make(x)
else Cons(x, this)
}
//@tailrec
final def append[B>:A](x: B): myList[B] ={
def appendrecc(lst:myList[B], a:B):myList[B]={
lst match {
case Nil =>Cons(a, Nil)
case x:myList[A]=> appendrecc(x,a)
}
}
Console.println(this.toString , x.toString)
if (this.isEmpty) make(x)
else Cons(this.head, this.tail.append(x))
}
def print()={
this.map(println)
}
def make[B>:A](x:B): myList[B] ={
this match {
case Cons(xh:B, xs:Cons[B]) => Cons(xh, xs.make(x))
case Cons(xh : B, Nil)=>Cons(xh,Cons(x, Nil))
case _=>Cons(x, Nil)
}
}
def map[A,B](f: (A) => B): myList[B] = {
this match {
case Cons(xh : A, Nil) => Cons(f(xh),Nil)
case Cons(xh:A, xs:Cons[A]) => Cons(f(xh),xs.map(f ))
case a:myList[A] =>Cons(f(a.head),a.tail.map(f ))
}
}
/**
* Combines all elements of this list into value.
*
* Time - O(n)
* Space - O(n)
*/
def fold[B](n: B)(op: (B, A) => B): B = {
def loop(l: myList[A], a: B): B =
if (l.isEmpty) a
else loop(l.tail, op(a, l.head))
loop(this, n)
}
def foldLeft[B](z: B)(f: (B, A) => B): B = {
var acc = z
var these = this
while (!these.isEmpty) {
acc = f(acc, these.head)
these = these.tail
}
acc
}
def foldRight[D,C](z: D)(f: (C, D) => D): D =
try {
// ...
this match {
case Cons(x:C,xs:Cons[C])=>{println("1case->"+this.toString);f(x, xs.foldRight(z)(f))}
case Cons(x:C, Nil) =>{println("2case->"+this.toString+"x->"+x.toString+"z-> "+z.toString);f(x,Nil.foldRight(z)(f))}
case y:C=>f(y,z)
}
} catch {
case e: Exception =>{ println(this.toString);e.printStackTrace(); sys.exit;}
}
def length[B>:A]():Int={
this match {
case _: myList[B] => foldRight(0) {(y:A,x:Int ) =>x+1
}
}
}
def appendprint[B>:A]():String={
this match {
case z: myList[B] => foldRight("") {(y:A, x:String ) =>
//Console.println(this)
y.toString+" --->"+x
}
}
}
def fail(m: String) = throw new NoSuchElementException(m)
}
case object Nil extends myList[Nothing]{
override def head: Nothing = fail("An empty list.")
override def tail: myList[Nothing] = fail("An empty list.")
override def isEmpty: Boolean = true
}
case class Cons[+A](headc: A, tailc: myList[A]) extends myList[A] {
override def isEmpty: Boolean = false
override def head():A ={
headc
}
override def tail():myList[A] ={
tailc
}
}
case class truck(
numberPlate:String
)
object myList {
/**
* An empty list.
*/
def empty[A]: myList[A] = Nil
/**
* A smart constructor for list's cons.
*/
def make[A](x: A, t: myList[A] = Nil): myList[A] = Cons(x, t)
/**
* Creates a new list from given 'xs' sequence.
*
* Time - O(n)
* Space - O(1)
*/
def apply[A](xs: A*): myList[A] = {
var r: myList[A] = myList.empty
for (x <- xs.reverse) r = r.append(x)
r
}
}
object Main {
def main(args: Array[String]) {
var a= new truck("1233bsd")
var b = new truck("dsads334")
var lst = List(a,b)
var e = myList(a,b)
Console.println(e)
Console.println("printing length of list ")
Console.println(e.length())
Console.println("copy list using fold operations------>")
var f=e.foldRight(Nil: myList[truck])((next, acc:myList[truck]) =>{println("fold function->"+next.toString); Cons[truck](next, acc)})
Console.println(f)
}
}
could you help building generic list list class using purely functional approach.
Errors , i am getting:-
(Nil,truck(dsads334))
(Cons(truck(dsads334),Nil),truck(1233bsd))
(Nil,truck(1233bsd))
Cons(truck(dsads334),Cons(truck(1233bsd),Nil))
printing length of list
1case->Cons(truck(dsads334),Cons(truck(1233bsd),Nil))
2case->Cons(truck(1233bsd),Nil)x->truck(1233bsd)z-> 0
3
copy list using fold operations------>
1case->Cons(truck(dsads334),Cons(truck(1233bsd),Nil))
2case->Cons(truck(1233bsd),Nil)x->truck(1233bsd)z-> Nil
Nil
java.lang.ClassCastException: Nil$ cannot be cast to scala.runtime.Nothing$
at Main$$anonfun$1.apply(mylist-v3.scala:193)
at myList.foldRight(mylist-v3.scala:98)
at myList.foldRight(mylist-v3.scala:97)
at myList.foldRight(mylist-v3.scala:96)
at Main$.main(mylist-v3.scala:193)
at Main.main(mylist-v3.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:101)
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:70)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
My approach may not be correct. i am looking solution too.
Upvotes: 0
Views: 790
Reputation: 780
You can bootstrap a MyList[A]
using the foldRight
method of scala.collection.List
:
List(Trunk("123"), Trunk("456"))
.foldRight(Nil: MyList[Trunk])((next, acc) => Cons(next, acc))
I wouldn't really consider this cheating, since Scala has special built-ins (variadic function application syntax) to construct lists from syntactically-built arrays, anyway.
Upvotes: 1