Java controller / Frege model

198 views
Skip to first unread message

griba

unread,
Jun 7, 2012, 10:32:42 AM6/7/12
to frege-program...@googlegroups.com
This is what I was looking for
and now it works !!

There is a Java ModelRoot class where to hook the Frege structure

The previously shown JFregeListIterator to retrieve the result list

The Model.fr with actions perfomed with ST.performUnsafe
(in this case 
    * modelInit hooks a list with 3 records to ModelRoot
    * modelAdd  call to prepend a new record with data from the Java caller
    * modelGetListIterator to get a result list iterator

Then, the Java JMain test class that calls the model actions.

To check it all just run at the unix prompt:

sh build.sh
-----------------
Maybe it can be done otherwise and I would like any criticism.

Later I will make an Android app with this.

Cheers!
Gabriel Riba.

JController_FregeModel.tgz

griba

unread,
Jun 7, 2012, 5:52:18 PM6/7/12
to frege-program...@googlegroups.com
Here it is in the Android Market !!!


If the link does not work because of line wrapping cuts, look for Frege in the Android market and you will see the Frege project logo.

Here I ask permission to use the "Frege project logo" for the sample app.

Cheers!

Gabriel Riba.

El dijous 7 de juny de 2012 16:32:42 UTC+2, griba va escriure:

griba

unread,
Jun 9, 2012, 7:20:50 AM6/9/12
to frege-program...@googlegroups.com
Android app. updated to a Handset friendly vertical layout.

I think that I should use IO.performUnsafe in the Model.fr instead of ST.performUnsafe but as IO is a synonim of (ST RealWorld) there is no difference of behaviour (If I'm not wrong!).

Cheers!
Gabriel.


El dijous 7 de juny de 2012 16:32:42 UTC+2, griba va escriure:
This is what I was looking for

Ingo W.

unread,
Jun 9, 2012, 7:17:34 PM6/9/12
to frege-program...@googlegroups.com


Am Samstag, 9. Juni 2012 13:20:50 UTC+2 schrieb griba:
Android app. updated to a Handset friendly vertical layout.

I think that I should use IO.performUnsafe in the Model.fr instead of ST.performUnsafe but as IO is a synonim of (ST RealWorld) there is no difference of behaviour (If I'm not wrong!).

Hi Gabriel,

it's actually no difference, except for readability.
Unfortunately, I couldn't install the app on my phone, I guess my Android version is too old. Oh well, my phone is more than a year old ....

Anyway, great work!

griba

unread,
Jun 10, 2012, 5:44:48 AM6/10/12
to frege-program...@googlegroups.com
>> Unfortunately, I couldn't install the app on my phone, I guess my Android version is too old. Oh well, my phone is more than a year old ....

The lowest Android SDK available for Java6 is v.2.3.3 which is API level 10. (Android 2.3.0 (API level 9) has been discontinued).

The sets compatible are tablets with Android 3.0+, or more recent handsets and tablets with Android 2.3.3.

Regards.
Gabriel Riba.

El diumenge 10 de juny de 2012 1:17:34 UTC+2, Ingo W. va escriure:

griba

unread,
Jun 10, 2012, 6:09:09 AM6/10/12
to frege-program...@googlegroups.com
Here are the Android controller and the updated Model.fr

// ------------------------------------------
package com.xarxaire.griba.fregedemo;


import com.xarxaire.griba.fregedemo.R;  // resources

import com.xarxaire.griba.fregedemo.Model ;
import com.xarxaire.griba.fregedemo.Model.TSample ;
import com.xarxaire.griba.fregedemo.JFregeIterator ;
import frege.rt.Box ;

// ... other android and Java imports

public class Android_FregeDemoActivity extends Activity {
public final static String CITY = "city" ;
public final static String CTDATA = "ctdata" ;
final String [] FROM     = {CITY, CTDATA,} ;
final int [] TO       = {R.id.city, R.id.ctdata, } ;
    final static Box.Int unit = Box.Int.mk(0) ;
ListView myListView ;
 
LinkedList<TreeMap<String, ?>> rowList ;
EditText etCity, etCityData ;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
     myListView = (ListView) findViewById(R.id.mylist) ;
     myListView.setOnItemClickListener(new MyListHandler( this)) ;
     
     etCity = (EditText) findViewById(R.id.etCity) ;;
     etCityData = (EditText) findViewById(R.id.etCityData) ;
     
     Model.modelInit( unit) ;

    }
    
    @Override
    public void onStart() {
    showModelData() ;
    super.onStart() ;
    }
  
public void addToList(View v) {
String city = etCity.getText().toString() ;
String ctData = etCityData.getText().toString() ;
int intCityData = Integer.valueOf( ctData) ;
myModelAdd( city, intCityData) ;
}
    
    
    private void myModelAdd(String city, int ctdata) {
        Model.modelAdd( Box.<String>mk(city), Box.Int.mk(ctdata)) ;
        showModelData() ;
        Toast.makeText(this, "Added in the Frege model", Toast.LENGTH_LONG).show() ;
    }
    
private void myModelRemove( String city) {
        Model.modelRemove( Box.<String>mk(city)) ;
        showModelData() ;
        Toast.makeText(this, "Removed in the Frege model", Toast.LENGTH_LONG).show() ;
    }
    
    @SuppressWarnings("rawtypes")
private void showModelData() {
   
        @SuppressWarnings("unchecked")
JFregeIterator<TSample> iter = (JFregeIterator<TSample>) ((Box<JFregeIterator>) Model.modelGetListIterator( unit)).j ;

        rowList = new LinkedList<TreeMap<String, ?>>() ; 
        TreeMap<String, Object> row ;
        
        
        while (iter.hasNext()) {
        row = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER) ;

            try {
TSample obj = (TSample) iter.next() ; 
String city = TSample.city( obj) ;
int ctdata = TSample.amount( obj) ;
row.put( CITY, city) ;
row.put( CTDATA, ctdata) ;
rowList.addLast( row) ;
            }
            catch (NoSuchElementException e) {
            // no envisaged
                System.out.println( e.getMessage()) ;
            }  
        }

     // Set up data binding
    SimpleAdapter adapter = new SimpleAdapter (this, rowList, R.layout.item, FROM, TO) ;
    myListView.setAdapter(adapter);
  }
    
    class MyListHandler implements OnItemClickListener {
    Context ctx ;
    MyListHandler( Context ctx) {
    this.ctx = ctx ;
    }

public void onItemClick(AdapterView<?> parent, View v, int pos,
long id) {
final String myCity = (String) rowList.get((int) id).get(CITY) ;
// Delete confirmation
new AlertDialog.Builder(ctx)
       .setIcon(android.R.drawable.ic_dialog_alert)
       .setTitle("Confirm delete")
       .setMessage("Delete entry \""+myCity+"\" ?")
       .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {

           public void onClick(DialogInterface dialog, int which) {

            myModelRemove( myCity) ;    
           }
       })
       .setNegativeButton(android.R.string.no, null)
       .show();
}
    }
}
// ------------------------------------------
// ------------------------------------------

--------------------------------------------
-- Model.fr
--------------------------------------------
module com.xarxaire.griba.fregedemo.Model where

data MyJFregeIterator s = native JFregeIterator where
    pure native new JFregeIterator.getInstance :: [t] -> (MyJFregeIterator s)

data Sample = Sample {city::String, amount::Int}
derive Eq Sample 

sampleList = [Sample "Paris" 2, Sample "Berlin" 3, Sample  "Barcelona" 1]
    
data JModelRoot myStructure s = native ModelRoot where
        -- instance methods
        native getModelStructure :: JModelRoot myStructure RealWorld -> IO myStructure
        native setModelStructure :: JModelRoot myStructure RealWorld -> myStructure -> IO ()

type MyStructure = [Sample] 
type MyModelRoot = JModelRoot MyStructure RealWorld
        
-- static methods
native jmrInitSingleton ModelRoot.initSingleton :: MyStructure -> IO MyModelRoot
native jmrGetInstance ModelRoot.getInstance :: () -> IO (Maybe MyModelRoot)

modelInit () = IO.performUnsafe (jmrInitSingleton( sampleList))

modelAdd :: String -> Int -> ()
modelAdd mycity amt = IO.performUnsafe (modelDoAdd mycity amt)

modelDoAdd :: String -> Int -> IO ()
modelDoAdd mycity amt 
= do
maybeInstance <- jmrGetInstance ()
case maybeInstance of
                Nothing -> error "you should initialise modelRoot first"
                Just modelRoot -> do {
myList <- modelRoot.getModelStructure ;
modelRoot.setModelStructure ((Sample mycity amt) : myList) ;
}

modelRemove myCity = IO.performUnsafe (modelDoRemove myCity)

modelDoRemove :: String -> IO ()
modelDoRemove myCity = do
maybeInstance <- jmrGetInstance ()
case maybeInstance of
                Nothing -> error "you should initialise modelRoot first"
                Just modelRoot -> do {
myList <- modelRoot.getModelStructure ;
let newList = filter (\(obj :: Sample) -> obj.city != myCity) myList
in modelRoot.setModelStructure (newList) ;
}

modelGetListIterator () = IO.performUnsafe (modelReturnListIterator ())

modelReturnListIterator :: () -> IO (MyJFregeIterator RealWorld)
modelReturnListIterator ()
= do
myInstance <- jmrGetInstance ()
case myInstance of
                Nothing -> error "you should initialise modelRoot first"
                Just modelRoot -> do {
myList <- modelRoot.getModelStructure ;
return (MyJFregeIterator.new (myList :: MyStructure)) ;
}
--------------------------------------------
--------------------------------------------

Thanks to you for the Frege compiler!!

I have problems with ''do'' subblocs parsing, so I used the semicolon separated syntax { ; ; }

Cheers!
Gabriel Riba.


El diumenge 10 de juny de 2012 1:17:34 UTC+2, Ingo W. va escriure:

griba

unread,
Jun 10, 2012, 6:36:09 AM6/10/12
to frege-program...@googlegroups.com
The last sentence should not have had the type annotation, since it's a list (PreludeBase.TList) what was expected. It should be:

modelReturnListIterator :: () -> IO (MyJFregeIterator RealWorld)
modelReturnListIterator ()
= do
myInstance <- jmrGetInstance ()
case myInstance of
                Nothing -> error "you should initialise modelRoot first"
                Just modelRoot -> do {
myList <- modelRoot.getModelStructure ;
return (MyJFregeIterator.new myList) ;
}

-----
Cheers!


El diumenge 10 de juny de 2012 12:09:09 UTC+2, griba va escriure:

Ingo W.

unread,
Jun 10, 2012, 6:36:37 AM6/10/12
to frege-program...@googlegroups.com


Am Sonntag, 10. Juni 2012 12:09:09 UTC+2 schrieb griba:
 
[ ... ]
I have problems with ''do'' subblocs parsing, so I used the semicolon separated syntax { ; ; }


This works, though it shouldn't be necessary.
Just make sure you don't use tabs for indentation.


griba

unread,
Jun 10, 2012, 6:40:04 AM6/10/12
to frege-program...@googlegroups.com
I was wrong with my last post, as the type annotation was a list.

Sorry.

El diumenge 10 de juny de 2012 12:36:09 UTC+2, griba va escriure:

griba

unread,
Jun 10, 2012, 8:00:31 AM6/10/12
to frege-program...@googlegroups.com
Is there an established way to make a function from a data record named field ?

I have updated the code to get a sorted list result, so the last Model function looks like:

modelReturnListIterator :: () -> IO (MyJFregeIterator RealWorld)
modelReturnListIterator () = do
maybeInstance <- jmrGetInstance ()
case maybeInstance of
                Nothing -> error "you should initialise modelRoot first"
                Just modelRoot -> modelReturnListIteratorOverSortedStructure modelRoot
 

modelReturnListIteratorOverSortedStructure (modelRoot::JModelRoot MyStructure RealWorld) = do
    myList <- modelRoot.getModelStructure 
    return (MyJFregeIterator.new (sortBy (comparing sampleCity) myList)) 
  where
      sampleCity (obj::Sample) = obj.city 
---------------------------------------------------------------
Regards.

El diumenge 10 de juny de 2012 12:36:37 UTC+2, Ingo W. va escriure:

Ingo W.

unread,
Jun 10, 2012, 9:24:51 AM6/10/12
to frege-program...@googlegroups.com


Am Sonntag, 10. Juni 2012 14:00:31 UTC+2 schrieb griba:
Is there an established way to make a function from a data record named field ?

In your case here: Sample.city
Generally, T.f, where T is the type constructor of the record and f is the field name.
 

griba

unread,
Jun 10, 2012, 10:27:00 AM6/10/12
to frege-program...@googlegroups.com
The editor in Eclipse introduces tabs by default  that cause the parsing problems with ''do'' subblocs.

I have seen that the eclipse preferences for Frege has a Checkbox named "Tab inserts spaces" that is unchecked by default. 

Maybe the FregeIDE setup page should advise to check the checkbox.

-----------------------------------------------------------------------------------------------
Now, introducing (>>>) the arrow left-to-right function composition the code is cleaner:

import Data.List (sortBy)

data MyJFregeIterator s = native JFregeIterator where
    pure native new JFregeIterator.getInstance :: [t] -> (MyJFregeIterator s)

data Sample = Sample {city::String, amount::Int}
derive Eq Sample 

sampleList = [Sample "Paris" 2, Sample "Berlin" 3, Sample  "Barcelona" 1]
    
data JModelRoot myStructure s = native ModelRoot where
        -- instance methods
        native getModelStructure :: JModelRoot myStructure RealWorld -> IO myStructure
        native setModelStructure :: JModelRoot myStructure RealWorld -> myStructure -> IO ()

type MyStructure = [Sample] 
type MyModelRoot = JModelRoot MyStructure RealWorld
        
-- static methods
native jmrInitSingleton ModelRoot.initSingleton :: MyStructure -> IO MyModelRoot
native jmrGetInstance ModelRoot.getInstance :: () -> IO (Maybe MyModelRoot)

modelInit () = IO.performUnsafe (jmrInitSingleton( sampleList))

infixr 3 `>>>`  
f >>> g = g • f

modelAdd :: String -> Int -> ()
modelAdd mycity amt = IO.performUnsafe (modelDoAdd mycity amt)

modelDoAdd :: String -> Int -> IO ()
modelDoAdd mycity amt = do
  maybeInstance <- jmrGetInstance ()
  case maybeInstance of
    Nothing -> error "you should initialise modelRoot first"
    Just modelRoot ->  
         modelRoot.getModelStructure >>= ((Sample mycity amt :) >>> modelRoot.setModelStructure)

modelRemove myCity = IO.performUnsafe (modelDoRemove myCity)

modelDoRemove :: String -> IO ()
modelDoRemove myCity = do
  maybeInstance <- jmrGetInstance ()
  case maybeInstance of
    Nothing -> error "you should initialise modelRoot first"
    Just modelRoot -> do 
        modelRoot.getModelStructure >>= ((filter notMyCity) >>> modelRoot.setModelStructure)   
      where
        -- pointFree
        notMyCity = Sample.city >>> (!= myCity)  

modelGetListIterator () = IO.performUnsafe (modelReturnListIterator ())

modelReturnListIterator :: () -> IO (MyJFregeIterator RealWorld)
modelReturnListIterator () = do
  maybeInstance <- jmrGetInstance ()
  case maybeInstance of
    Nothing -> error "you should initialise modelRoot first"
    Just modelRoot ->
       modelRoot.getModelStructure >>= (sortBy (comparing Sample.city) >>> MyJFregeIterator.new >>> return)

----------------------------------------------------------------------------
Regards!


El diumenge 10 de juny de 2012 15:24:51 UTC+2, Ingo W. va escriure:

Ingo W.

unread,
Jun 10, 2012, 3:43:56 PM6/10/12
to frege-program...@googlegroups.com


Am Sonntag, 10. Juni 2012 16:27:00 UTC+2 schrieb griba:
The editor in Eclipse introduces tabs by default  that cause the parsing problems with ''do'' subblocs.

I have seen that the eclipse preferences for Frege has a Checkbox named "Tab inserts spaces" that is unchecked by default.

No, it should be  checked by default.
The trouble is that too many preferences (General Editor, Java Editor, IMP Editor, Language Specific Editor) influence this.

 
Maybe the FregeIDE setup page should advise to check the checkbox.

Yes, I think I'll make it clear in the  tutorial more explicitly.

Reply all
Reply to author
Forward
0 new messages