functional
v6.0.0
Pustaka pemrograman fungsional PHP. Monad dan fungsi penggunaan umum.
Metode instalasi yang didukung adalah melalui komposer:
$ composer require fp4php/functionalSilakan merujuk ke repositori fp4php/fungsional-psalm-plugin.
Jenis yang aman dan ringkas.
Kombinasi yang kuat: Koleksi + Opsi Monad.
<?php
use Fp Collections ArrayList ;
use Fp Functional Option Option ;
use function Fp Evidence of ;
use function Fp Evidence proveString ;
class PgSqlCurrencyArrayType extends Type
{
public function convertToDatabaseValue ( $ value , AbstractPlatform $ platform ): string
{
$ currencies = Option:: fromNullable ( $ value )
-> filter ( is_iterable (...))
-> getOrElse ([]);
return ArrayList:: collect ( $ currencies )
-> flatMap ( of (Currency::class))
-> map ( fn ( Currency $ currency ) => $ currency -> getCurrencyCode ())
-> mkString ( ' { ' , ' , ' , ' } ' );
}
/**
* @return ArrayList<Currency>
*/
public function convertToPHPValue ( $ value , AbstractPlatform $ platform ): ArrayList
{
$ csv = Option:: fromNullable ( $ value )
-> flatMap ( proveString (...))
-> map ( fn ( string $ pgSqlArray ) => trim ( $ pgSqlArray , ' {} ' ))
-> getOrElse ( '' );
return ArrayList:: collect ( explode ( ' , ' , $ csv ))
-> filterMap ( $ this -> parseCurrency (...));
}
/**
* @return Option<Currency>
*/
public function parseCurrency ( string $ currencyCode ): Option
{
return Option:: try ( fn () => Currency:: of ( $ currencyCode ));
}
} <?php
use Fp Collections NonEmptyLinkedList ;
/**
* Inferred type is NonEmptyLinkedList<1|2|3>
*/
$ collection = NonEmptyLinkedList:: collectNonEmpty ([ 1 , 2 , 3 ]);
/**
* Inferred type is NonEmptyLinkedList<int>
*
* Literal types are dropped after map transformation,
* but NonEmpty collection prefix has been kept
*/
$ mappedCollection = $ collection -> map ( fn ( $ elem ) => $ elem - 1 );
/**
* Inferred type is LinkedList<positive-int>
* NonEmpty prefix has been dropped
*/
$ filteredCollection = $ mappedCollection -> filter ( fn ( int $ elem ) => $ elem > 0 ); <?php
use Tests Mock Foo ;
use Tests Mock Bar ;
use Fp Collections NonEmptyArrayList ;
$ source = [ new Foo ( 1 ), null , new Bar ( 2 )];
/**
* Inferred type is ArrayList<Foo|Bar>
* Null type was removed
* NonEmpty prefix was removed
*/
$ withoutNulls = NonEmptyArrayList:: collectNonEmpty ( $ source )
-> filter ( fn ( Foo | Bar | null $ elem ) => null !== $ elem );
/**
* Inferred type is ArrayList<Foo>
* Bar type was removed
*/
$ onlyFoos = $ withoutNulls -> filter ( fn ( $ elem ) => $ elem instanceof Foo); <?php
use Fp Collections NonEmptyLinkedList ;
class User {}
class Admin extends User {}
/**
* @param NonEmptyLinkedList<User> $collection
*/
function acceptUsers ( NonEmptyLinkedList $ collection ): void {}
/**
* @var NonEmptyLinkedList<Admin> $collection
*/
$ collection = NonEmptyLinkedList:: collectNonEmpty ([ new Admin ()]);
/**
* You can pass collection of admins instead of users
* Because of covariant template parameter
*/
acceptUsers ( $ collection ); <?php
use Fp Collections LinkedList ;
$ originalCollection = LinkedList:: collect ([ 1 , 2 , 3 ]);
/**
* $originalCollection won't be changed
*/
$ prependedCollection = $ originalCollection -> prepended ( 0 );
/**
* $prependedCollection won't be changed
*/
$ mappedCollection = $ prependedCollection -> map ( fn ( int $ elem ) => $ elem + 1 ); <?php
use Fp Functional Option Option ;
use Fp Collections ArrayList ;
/**
* @var ArrayList<int> $collection
*/
$ collection = getCollection ();
/**
* @return Option<float>
*/
function div ( int $ a , int $ b ): Option
{
return Option:: when ( 0 !== $ b , fn () => $ a / $ b );
}
/**
* It's possible there is no first collection element above zero
* or divisor is zero.
*
* In this case the execution will short circuit (stop)
* and no Null Pointer Exception will be thrown.
*/
$ collection
-> first ( fn ( int $ elem ) => $ elem > 0 )
-> map ( fn ( int $ elem ) => $ elem + 1 )
-> flatMap ( fn ( int $ elem ) => div ( $ elem , $ elem - 1 ))
-> getOrElse ( 0 ) <?php
use Tests Mock Foo ;
use Fp Functional Option Option ;
use function Fp Evidence proveTrue ;
use function Fp Evidence proveNonEmptyList ;
/**
* Inferred type is Option<Foo>
*/
$ maybeFooMaybeNot = Option:: do ( function () use ( $ untrusted ) {
// If $untrusted is not null then bind this value to $notNull
$ notNull = yield Option:: fromNullable ( $ untrusted );
// If $notNull is non-empty-list<TestsMockFoo> then bind this value to $nonEmptyListOfFoo
$ nonEmptyList = yield proveNonEmptyList ( $ notNull , of (Foo::class));
// Continue computation if $nonEmptyList contains only one element
yield proveTrue ( 1 === count ( $ nonEmptyList ));
// I'm sure it's Foo object
return $ nonEmptyList [ 0 ];
});
// Inferred type is TestsMockFoo
$ foo = $ maybeFooMaybeNot -> getOrCall ( fn () => new Foo ( 0 ));$ sudo apt install pandoc$ make