블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2809)
Unity3D (865)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (234)
협업 (61)
3DS Max (3)
Game (12)
Utility (140)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

람다 식

Programming/C# / 2014. 8. 29. 14:16

출처 : http://msdn.microsoft.com/ko-kr/library/bb397687.aspx



람다 식(C# 프로그래밍 가이드)

Visual Studio 2013
3명 중 3명이 도움이 되는 것으로 평가 이 항목 평가

람다 식은 대리자 또는 식 트리 형식을 만드는 데 사용할 수 있는 익명 함수입니다. 람다 식을 사용하여 인수로 전달되거나 함수 호출 값으로 반환되는 로컬 함수를 쓸 수 있습니다. 람다 식은 LINQ 쿼리 식을 작성하는 데 특히 유용합니다.

람다 식을 만들려면 람다 연산자 => 왼쪽에 입력 매개 변수를 지정하고(있는 경우) 다른 쪽에 식이나 문 블록을 삽입합니다. 예를 들어 람다 식 x => x * x는 이름이 x인 매개 변수를 지정하고 x 제곱 값을 반환합니다. 다음 예제와 같이 대리자 형식에 이 식을 할당할 수도 있습니다.

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

식 트리 형식을 만들려면

using System.Linq.Expressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<del> myET = x => x * x;
        }
    }
}

=> 연산자는 할당(=)과 우선 순위가 같고 오른쪽 결합성이 있습니다(연산자 문서의 "결합성" 단원 참조).

람다 식은 메서드 기반 LINQ 쿼리에서 Where 같은 표준 쿼리 연산자 메서드의 인수로 사용됩니다.

LINQ to Objects 및 LINQ to XML에서처럼 메서드 기반의 구문을 사용하여 Enumerable 클래스에서 Where 메서드를 호출하는 경우 매개 변수는System.Func<T, TResult> 대리자 형식입니다. 람다 식은 이러한 대리자를 만드는 가장 간단한 방법입니다. 예를 들어 LINQ to SQL에서처럼 이 메서드를System.Linq.Queryable 클래스에서 호출하는 경우 매개 변수 형식은 System.Linq.Expressions.Expression<Func>이고, 여기서 Func는 입력 매개 변수를 16개까지 가질 수 있는 임의의 Func 대리자입니다. 이 경우에도 람다 식을 사용하면 식 트리를 간단하게 만들 수 있습니다. 람다 식은 Where 호출과 비슷하게 보일 수 있지만 실제로 람다 식을 통해 생성되는 개체 형식은 다릅니다.

위의 예제에서 대리자 시그니처는 형식이 암시적으로 지정된 int 형식의 입력 매개 변수 하나를 포함하고 int를 반환합니다. 람다 식에도 입력 매개 변수 하나(x)와 컴파일러에서 int 형식으로 암시적으로 변환할 수 있는 반환 값이 있기 때문에 람다 식을 이 형식의 대리자로 변환할 수 있습니다. 형식 유추는 다음 단원에서 자세하게 설명합니다. 입력 매개 변수를 5로 사용하여 대리자를 호출하면 25라는 결과가 반환됩니다.

is 또는 as 연산자의 왼쪽에는 람다 식을 사용할 수 없습니다.

무명 메서드에 적용되는 모든 제한은 람다 식에도 적용됩니다. 자세한 내용은 무명 메서드(C# 프로그래밍 가이드)을 참조하십시오.

=> 연산자의 오른쪽에 식이 있는 람다 식을 식 람다라고 합니다. 식 람다는 식 트리(C# 및 Visual Basic)를 만드는 데 광범위하게 사용됩니다. 식 람다는 식의 결과를 반환하며 기본 형식은 다음과 같습니다.

(input parameters) => expression

괄호는 람다 식에 입력 매개 변수가 하나뿐인 경우에만 생략할 수 있고 그렇지 않으면 생략할 수 없습니다. 둘 이상의 입력 매개 변수는 다음과 같이 괄호로 묶고 쉼표로 구분해야 합니다.

(x, y) => x == y

컴파일러에서 입력 형식을 유추할 수 없는 경우도 있습니다. 이와 같은 경우에는 다음 예제와 같이 형식을 명시적으로 지정할 수 있습니다.

(int x, string s) => s.Length > x

입력 매개 변수가 0개이면 다음과 같이 빈 괄호를 지정합니다.

() => SomeMethod()

위의 예제에서 식 람다의 본문은 메서드 호출로 구성될 수 있습니다. 하지만 SQL Server와 같은 .NET Framework 외부에서 평가되는 식 트리를 만드는 경우에는 람다 식에 메서드 호출을 사용하지 않아야 합니다. 이러한 메서드는 .NET 공용 언어 런타임의 컨텍스트 안에서만 의미가 있습니다.

문 람다는 다음과 같이 중괄호 안에 문을 지정한다는 점을 제외하면 식 람다와 비슷합니다.

(input parameters) => {statement;}

문 람다의 본문에 지정할 수 있는 문의 개수에는 제한이 없지만 일반적으로 2-3개 정도만 지정합니다.

delegate void TestDelegate(string s);
…
TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };
myDel("Hello");

무명 메서드와 마찬가지로 문 람다는 식 트리를 만드는 데 사용할 수 없습니다.

async 및 await 키워드를 사용하여 비동기 처리를 통합하는 람다 식과 문을 쉽게 만들 수 있습니다. 예를 들어 다음 Windows Forms 예제에는 비동기 메서드 ExampleMethodAsync를 호출하고 기다리는 이벤트 처리기가 포함되어 있습니다.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        // ExampleMethodAsync returns a Task.
        await ExampleMethodAsync();
        textBox1.Text += "\r\nControl returned to Click event handler.\r\n";
    }

    async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

비동기 람다를 사용하여 동일한 이벤트 처리기를 추가할 수 있습니다. 이 처리기를 추가하려면 다음 예제에 표시된 것처럼 람다 매개 변수 목록에 async 한정자를 추가합니다.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += async (sender, e) =>
        {
            // ExampleMethodAsync returns a Task.
            await ExampleMethodAsync();
            textBox1.Text += "\r\nControl returned to Click event handler.\r\n";
        };
    }

    async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

비동기 메서드를 만들고 사용하는 방법에 대한 자세한 내용은 Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)을 참조하십시오.

대부분의 표준 쿼리 연산자에는 형식이 제네릭 대리자의 Func<T, TResult> 패밀리 중 하나인 입력 매개 변수를 사용합니다. 이러한 대리자는 형식 매개 변수를 사용하여 입력 매개 변수의 수와 형식 및 대리자의 반환 형식을 정의합니다. Func 대리자는 소스 데이터 집합에 있는 각 요소에 적용할 사용자 정의 식을 캡슐화하는 데 매우 유용합니다. 다음 대리자 형식을 예로 들 수 있습니다.

public delegate TResult Func<TArg0, TResult>(TArg0 arg0)

이 경우 대리자를 Func<int,bool> myFunc로 인스턴스화할 수 있습니다. 여기서 int는 입력 매개 변수이고, bool은 반환 값입니다. 반환 값은 항상 마지막 형식 매개 변수에 지정됩니다. Func<int, string, bool>는 두 입력 매개 변수로 int 형식과 string 형식을 사용하여 대리자를 정의하고 bool 형식을 반환합니다. 다음 Func 대리자를 호출하면 입력 매개 변수가 5인지 여부를 나타내는 true 또는 false가 반환됩니다.

Func<int, bool> myFunc = x => x == 5;
bool result = myFunc(4); // returns false of course

System.Linq.Queryable에 정의되어 있는 표준 쿼리 연산자의 경우와 같이 인수 형식이 Expression<Func>인 경우에도 람다 식을 사용할 수 있습니다.Expression<Func> 인수를 지정하면 식 트리에 람다 식이 컴파일됩니다.

다음 코드에서는 표준 쿼리 연산자인 Count 메서드를 보여 줍니다.

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);

컴파일러에서 입력 매개 변수의 형식을 유추하거나 사용자가 형식을 명시적으로 지정할 수 있습니다. 이 람다 식은 2로 나누었을 때 나머지가 1인 정수(n)의 수를 계산합니다.

다음 코드 줄은 숫자 시퀀스에서 조건을 만족하지 않는 첫 번째 숫자가 "9"이기 때문에 numbers 배열에서 "9" 왼쪽에 있는 모든 요소가 포함된 시퀀스를 생성합니다.

var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);

이 예제에서는 괄호로 묶어 입력 매개 변수를 여러 개 지정하는 방법을 보여 줍니다. 이 메서드는 값이 해당 위치보다 작은 숫자를 발견할 때까지 숫자 배열의 모든 요소를 반환합니다. 여기서 람다 연산자(=>)를 크거나 같음 연산자(>=)와 혼동하면 안 됩니다.

var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);

컴파일러에서는 람다 식 본문, 매개 변수의 대리자 형식 및 C# 언어 사양에 설명되어 있는 기타 요소를 기준으로 형식을 유추할 수 있기 때문에 대부분의 경우에는 람다 식을 작성할 때 입력 매개 변수의 형식을 지정하지 않아도 됩니다. 대부분의 표준 쿼리 연산자에서 첫 번째 입력 형식은 소스 시퀀스 요소의 형식입니다. 따라서 IEnumerable<Customer>를 쿼리할 경우 입력 변수가 Customer 개체로 유추됩니다. 이는 이 개체의 메서드와 속성에 액세스할 수 있음을 의미합니다.

customers.Where(c => c.City == "London");

람다 식에는 다음과 같은 일반적인 규칙이 적용됩니다.

  • 람다 식과 대리자 형식에 포함된 매개 변수 수가 같아야 합니다.

  • 람다 식의 각 입력 매개 변수는 해당되는 대리자 매개 변수로 암시적으로 변환될 수 있어야 합니다.

  • 람다 식의 반환 값(있는 경우)은 대리자의 반환 형식으로 암시적으로 변환될 수 있어야 합니다.

공용 형식 시스템에는 "람다 식"이라는 개념이 기본적으로 포함되어 있지 않기 때문에 람다 식 자체에는 형식이 없습니다. 그러나 람다 식의 "형식"을 비공식적으로 언급해야 할 경우도 있는데 이 경우 형식은 대리자 형식 또는 람다 식이 변환되는 Expression 형식을 의미합니다.

람다 식은 람다 함수를 정의하는 메서드 범위 내에 있거나 람다 식을 포함하는 형식 범위 내에 있는 외부 변수(무명 메서드(C# 프로그래밍 가이드) 참조)를 참조할 수 있습니다. 이러한 방식으로 캡처되는 변수는 변수가 범위를 벗어나 가비지 수집되는 경우에도 람다 식에 사용할 수 있도록 저장됩니다. 외부 변수는 명확하게 할당해야만 람다 식에 사용할 수 있습니다. 다음 예제에서는 이러한 규칙을 보여 줍니다.

delegate bool D();
delegate bool D2(int i);

class Test
{
    D del;
    D2 del2;
    public void TestMethod(int input)
    {
        int j = 0;
        // Initialize the delegates with lambda expressions.
        // Note access to 2 outer variables.
        // del will be invoked within this method.
        del = () => { j = 10;  return j > input; };

        // del2 will be invoked after TestMethod goes out of scope.
        del2 = (x) => {return x == j; };
      
        // Demonstrate value of j:
        // Output: j = 0 
        // The delegate has not been invoked yet.
        Console.WriteLine("j = {0}", j);        // Invoke the delegate.
        bool boolResult = del();

        // Output: j = 10 b = True
        Console.WriteLine("j = {0}. b = {1}", j, boolResult);
    }

    static void Main()
    {
        Test test = new Test();
        test.TestMethod(5);

        // Prove that del2 still has a copy of
        // local variable j from TestMethod.
        bool result = test.del2(10);

        // Output: True
        Console.WriteLine(result);
           
        Console.ReadKey();
    }
}

람다 식의 변수 범위에는 다음과 같은 규칙이 적용됩니다.

  • 캡처된 변수는 해당 변수를 참조하는 대리자가 가비지 수집 대상이 될 때까지 가비지 수집되지 않습니다.

  • 람다 식에 사용된 변수는 외부 메서드에 표시되지 않습니다.

  • 람다 식은 바깥쪽 메서드에서 ref 또는 out 매개 변수를 직접 캡처할 수 없습니다.

  • 람다 식의 return 문에 의해서는 바깥쪽 메서드가 반환되지 않습니다.

  • 점프문의 대상이 블록 외부에 있는 경우 람다 식에 람다 함수 내에 있는 goto 문, break 문 또는 continue 문을 포함할 수 없습니다. 대상이 블록 내에 있는 경우 람다 함수 블록 외부에 점프문을 사용해도 오류가 발생합니다.

자세한 내용은 C# 언어 사양을 참조하십시오. 이 언어 사양은 C# 구문 및 사용법에 대한 신뢰할 수 있는 소스입니다.


반응형

'Programming > C#' 카테고리의 다른 글

Calendar Class[MSDN]  (0) 2014.09.01
C# 강의  (0) 2014.08.29
Get Dictionary key by using the dictionary value  (0) 2014.08.12
[C#] How to get/set using index for a Dictionary?  (0) 2014.08.06
NTP 서버에서 시간 가져오기(SNTP)  (0) 2014.07.14
Posted by blueasa
, |


Link : http://blog.goldface.kr/6

반응형
Posted by blueasa
, |



링크 : http://blog.naver.com/ksk9905007/140109999063

반응형

'재테크 > 주식' 카테고리의 다른 글

[링크] 경기순환시계  (0) 2019.05.23
밑꼬리 양봉과 음봉  (0) 2014.06.18
실전 최적 매수패턴 22선  (0) 2014.06.18
이동평균선  (0) 2014.06.12
키움증권 영웅문을 통한 스탑로스(Stoploss) 사용 방법  (0) 2014.05.28
Posted by blueasa
, |





화면에 나타나는 특정 버튼이나 링크 혹은 텍스트를 클릭하고 싶은 경우가 있죠.
좌표로만 처리 할 경우 클릭하고 싶은 대상의 위치가 변하는 경우 원하는 결과를 얻을 수 없습니다.

예를 들어서 네이버 메인 화면에서 로그인 버튼을 클릭하고 싶을때
좌표값을 이용해도 가능은 하지만 조금 더 신뢰할 수 있는 방법으로 imagesearch를 사용할 수 있습니다.


여기서 로그인버튼을 클릭해 보는 경우를 들자면...
우선 네이버 메인 화면의 스크린샷을 만든 후 1과 같이 영역을 선택하고 저장해 봅시다.
(저장하실때 파일명은 login.jpg로 해주세요.)

1.



만약 다음(2번)과 같이 영역을 선택한다면

2. 


imagesearch 명령어는 찾고 있는 이미지의 좌측상단 좌표를 반환하기 때문에
2와 같이 캡쳐할 경우 마우스로 클릭할 좌표를 얻기 위해서는 또 계산이 필요합니다.
그래서 처음부터 1의 예처럼 캡쳐를 하면 좌표 계산 없이 바로 얻어진 좌표값을 사용할 수 있습니다.

imagesearch명령의 기본 형태는 다음과 같습니다.

ImageSearch, OutputVarX, OutputVarY, X1, Y1, X2, Y2, ImageFile

OutputVarX, OutputVarY : ImageFile과 일치하는 이미지의 좌표값
X1, Y1, X2, Y2 : 이미지를 검색할 범위

그러면 다음과 같이 스크립트를 만들어 봅시다.
(물론 스크립트가 존재하는 폴더에 login.jpg가 있다고 가정할 경우입니다.)

^f::
ImageSearch, vX,vY,1,1,1024,768,login.jpg
mousemove,%vX%,%vY%
return

네이버창이 떠있는 상태에서 콘트롤-f 해주시면 마우스가 로그인 버튼 위로 이동하는 것을 확인하실 수 있습니다.


출처 : http://www.autohotkey.co.kr/cgi/board.php?bo_table=tip&wr_id=19&page=3

반응형

'Utility > AutoHotKey' 카테고리의 다른 글

AutoHotKey 관련 사이트  (0) 2014.07.09
Posted by blueasa
, |

Extension Methods

Unity3D/Extensions / 2014. 8. 18. 02:30

Extension Methods

Posted by  on December 6th, 2013

Oftentimes you’ll find yourself using classes you can’t modify. Whether they’re basic data types or part of an existing framework, you’re stuck with the functions that are provided. That being said, C# provides a nifty trick to appending functions to classes! These are known as Extension Methods.

Extension methods are fairly simple to create and are frequently used as syntactic sugar. A practical example can be seen with Unity’s Transform class. Let’s say you want to set only the xvariable of Transform.position.

using UnityEngine;
using System.Collections;
 
public class Player : MonoBehaviour
{
    void Update ()
    {
        //Set new x position to 5
        transform.position = new Vector3(5f, transform.position.y, transform.position.z);
    }
}

In this case Transform.position gives you an error if you only try to assign its x member variable, so you have to assign the entire Vector3. An extension method such as SetPositionX() could be appended to the Transform class and help make this code more readable.

In order to create extension methods you have to create a static class. In addition, an extension method declaration must be declared static and have the first parameter be of the type that you’re writing the method for, preceded by the this keyword.

using UnityEngine;
using System.Collections;
 
//Must be in a static class
public static class Extensions
{
    //Function must be static
    //First parameter has "this" in front of type
    public static void SetPositionX(this Transform t, float newX)
    {
        t.position = new Vector3(newX, t.position.y, t.position.z);
    }
}

Now you can go back to your other script and replace our old code with the new extension method.

using UnityEngine;
using System.Collections;
 
public class Player : MonoBehaviour
{
    void Update ()
    {
        //Set new x position to 5
        transform.SetPositionX(5f);
    }
}
NOTE: Extension methods can only be called on an instance of a class, not on the class itself.

Here are a few more extension methods to get you started, as well as an example script that utilizes a few of them.

Extensions:

using UnityEngine;
using System.Collections;
 
public static class Extensions
{
    public static void SetPositionX(this Transform t, float newX)
    {
        t.position = new Vector3(newX, t.position.y, t.position.z);
    }
 
    public static void SetPositionY(this Transform t, float newY)
    {
        t.position = new Vector3(t.position.x, newY, t.position.z);
    }
 
    public static void SetPositionZ(this Transform t, float newZ)
    {
        t.position = new Vector3(t.position.x, t.position.y, newZ);
    }
 
    public static float GetPositionX(this Transform t)
    {
        return t.position.x;
    }
 
    public static float GetPositionY(this Transform t)
    {
        return t.position.y;
    }
 
    public static float GetPositionZ(this Transform t)
    {
        return t.position.z;
    }
 
    public static bool HasRigidbody(this GameObject gobj)
    {
        return (gobj.rigidbody != null);
    }
 
    public static bool HasAnimation(this GameObject gobj)
    {
        return (gobj.animation != null);
    }
 
    public static void SetSpeed(this Animation anim, float newSpeed)
    {
        anim[anim.clip.name].speed = newSpeed;
    }
}

Example Script:

using UnityEngine;
using System.Collections;
 
public class Player : MonoBehaviour
{
    void Update ()
    {
        //move x position 5 units
        float currentX = transform.GetPositionX();
        transform.SetPositionX(currentX + 5f);
 
        if(gameObject.HasRigidbody())
        {
            //Do something with physics!
        }
 
        if(gameObject.HasAnimation())
        {
            //Double the animation speed!
            gameObject.animation.SetSpeed(2f);
        }
    }
}
NOTE: Static classes do NOT extend MonoBehaviour.
ANOTHER NOTE: If you define your extension methods inside of a namespace, you have to declare the use of that namespace in order to bring them into scope.


출처 : http://unitypatterns.com/extension-methods/

반응형
Posted by blueasa
, |

Nullable Types

Unity3D/Extensions / 2014. 8. 18. 02:29

Nullable Types

Posted by  on January 14th, 2014

Sometimes you have variables that have important information but only after certain game events occur. For example: A character in your game may be idle until they’re told to go to an assigned destination.

public class Character : MonoBehaviour
{
    Vector3 targetPosition;
 
    void MoveTowardsTargetPosition()
    {
        if(targetPosition != Vector3.zero)
        {
            //Move towards the target position!
        }
    }
 
    public void SetTargetPosition(Vector3 newPosition)
    {
        targetPosition = newPosition;
    }
}

In this case, we want the character to move towards the target position only if it’s been assigned. In the code above, we do this by just checking if targetPosition is not equal to its default value (0, 0, 0).  But now we have an issue: what if you want your character to move to (0, 0, 0)? You don’t want to discredit the possibility of that value being used because it might come up sometime during the game!

Luckily, there’s a trick to help avoid comparing arbitrary values for confirming that a variable has been initialized: Nullable Types.

Using Nullable Types

To make a nullable type, just add a “?” after the type declaration of any variable that is a Value Type (eg. Vector3, Rect, int, float).

public class Character : MonoBehaviour
{
    //Notice the added "?"
    Vector3? targetPosition;
 
    void MoveTowardsTargetPosition()
    {
        if (targetPosition.HasValue)
        {
            //Move towards the target position!
            //use targetPosition.Value for the actual value
        }
    }
 
    public void SetTargetPosition(Vector3 newPosition)
    {
        targetPosition = newPosition;
    }
}

Seen here, nullable types have two properties we can use: HasValue (true if the variable has been assigned, false otherwise), and Value (the actual assigned value of the variable).

//First, check if the variable has been assigned a value
if (targetPosition.HasValue)
{
    //move towards targetPosition.Value
}
else
{
    //targetPosition.Value is invalid! Don't use it!
}

Usage Notes

  • To revert a nullable type to having “no value”, set it to null
  • You can NOT create nullable types from classes, or reference types (they can already be set to null)

As usual, if you have any questions or tips to add, do so in the comments below!



출처 : http://unitypatterns.com/nullable-types/

반응형

'Unity3D > Extensions' 카테고리의 다른 글

일괄적으로 Texture Import Setting 변경  (0) 2015.01.30
Extension Methods  (0) 2014.08.18
ObjectPool  (0) 2014.04.22
인스펙터 상의 GUI를 비활성화 시키고 싶을 때..  (0) 2014.04.02
Save Scene while on play mode  (0) 2014.01.12
Posted by blueasa
, |

Link : https://github.com/RyanNielson/awesome-unity



Awesome Unity

A curated list of awesome Unity assets, projects, and resources.

Inspired by awesome-rubyawesome-php, and awesome-python.

2D

  • 2d Toolkit - An efficient & flexible 2D sprite, collider set-up, text, tilemap and UI system.
  • Ferr2D Terrain Tool - Quickly create handcrafted 2D landscapes and levels.
  • SmoothMoves - A skeletal animation editor.
  • Spine - A skeletal animation editor with a Unity library.

AI

  • A* Pathfinding Project (Free and paid) - Lightning fast pathfinding with heavily optimized algorithms and a large feature set.
  • Rain (Free) - A toolset that provides integrated AI rigging, a visual behavior tree editor, pathfinding, automatic nav grid generation, and more.

Camera

  • UFPS - Provides camera, controllers, and other effects for use in FPS games.

Character Controllers

Frameworks

  • uFrame - Create maintainable games faster, better, more stable, and consistent than ever before.

Input

  • InControl (Free) - An input manager that tames makes handler cross-platform. controller input easy.
  • TouchKit (Free) - Makes it easy to recognize gestures and other touch input.

Networking

  • Bolt - Build networked games without having to know the details of networking or write any complex networking code.
  • Photon Unity Networking (Free) - Plug and play cloud networking that also works for local hosting. Free for up to 20 concurrent users.

Textures

Tweening

  • GoKit (Free) - An open source, lightweight tween library aimed at making tweening objects dead simple.
  • HOTween (Free) - Tween any numeric property or field (including Vectors, Rectangles, etc.), plus some non-numeric ones (like strings).
  • iTween (Free) - A simple, and easy to use animation system.
  • LeanTween (Free) - FOSS, and also the most lightweight tweening library for Unity. Allows you to tween any value you have access to via the .value() method.

UI

  • Daikon Forge - A user interface library that provides deep editor integration, data/event binding, and much more.
  • NGUI - A powerful UI system and event notification framework.

Visual Scripting

  • Playmaker - Quickly make gameplay prototypes, A.I. behaviors, animation graphs, interactive objects, and more using finite state machines.
  • Shader Forge - A node-based shader editor giving you the artistic freedom of shader creation, with no need to code.

Projects

A list of awesome projects made using Unity.

Resources

Tutorials

  • Catlike Coding - Tutorials designed for learning the C# scripting side of Unity.
  • Official Video Tutorials - The official tutorials for scripting, animation, audio, and almost anything Unity related.
  • Unity Patterns - Software pattern tutorials and free tools for Unity.

Contributing

Please see CONTRIBUTING for details.

반응형

'Unity3D > Link' 카테고리의 다른 글

unity3d grid  (0) 2014.12.19
Tree Pack(FBX)  (0) 2014.09.03
유니티 짱(Unity Chan)  (0) 2014.04.11
모바일 게임 버전 관리 정책  (0) 2014.02.25
유니티 C# 관련 사이트  (0) 2012.10.24
Posted by blueasa
, |


링크 : http://jdm0777.com/jilbyeong/bimunjeung.htm

반응형
Posted by blueasa
, |

Link : http://en.wikipedia.org/wiki/Monad_(functional_programming)



Monad (functional programming)

From Wikipedia, the free encyclopedia

In functional programming, a monad is a structure that represents computations defined as sequences of steps. A type with a monad structure defines what it means to chain operations, or nest functions of that type together. This allows the programmer to build pipelines that process data in steps, in which each action is decorated with additional processing rules provided by the monad.[1] As such, monads have been described as "programmable semicolons"; a semicolon is the operator used to chain together individual statements in many imperative programming languages,[1] thus the expression implies that extra code will be executed between the statements in the pipeline. Monads have also been explained with a physical metaphor as assembly lines, where a conveyor belt transports data between functional units that transform it one step at a time.[2] They can also be seen as a functional design pattern to build generic types.[3]

Purely functional programs can use monads to structure procedures that include sequenced operations like those found in structured programming.[4][5] Many common programming concepts can be described in terms of a monad structure, including side effects such as input/output, variable assignmentexception handling,parsingnondeterminismconcurrency, and continuations. This allows these concepts to be defined in a purely functional manner, without major extensions to the language's semantics. Languages like Haskell provide monads in the standard core, allowing programmers to reuse large parts of their formal definition and apply in many different libraries the same interfaces for combining functions.[6]

Formally, a monad consists of a type constructor M and two operations, bind and return (where return is often also called unit). The operations must fulfill several properties to allow the correct composition of monadicfunctions (i.e. functions that use values from the monad as their arguments or return value). The returnoperation takes a value from a plain type and puts it into a monadic container using the constructor, creating amonadic value. The bind operation performs the reverse process, extracting the original value from the container and passing it to the associated next function in the pipeline, possibly with additional checks and transformations. Because a monad can insert additional operations around a program's domain logic, monads can be considered a sort of aspect-oriented programming.[7] The domain logic can be defined by the application programmer in the pipeline, while required aside bookkeeping operations can be handled by a pre-defined monad built in advance.

The name and concept comes from the eponymous concept (monad) in category theory, where monads are one particular kind of functor, a mapping between categories; although the term monad in functional programming contexts is usually used with a meaning corresponding to that of the term strong monad in category theory.[8]

History[edit]

The concept of monad programming appeared in the 1980s in the programming language Opal even though it was called "commands" and never formally specified.[citation needed]

Eugenio Moggi first described the general use of monads to structure programs in 1991.[8] Several people built on his work, including programming language researchers Philip Wadler and Simon Peyton Jones (both of whom were involved in the specification of Haskell). Early versions of Haskell used a problematic "lazy list" model for I/O, and Haskell 1.3 introduced monads as a more flexible way to combine I/O with lazy evaluation.

In addition to I/O, programming language researchers and Haskell library designers have successfully applied monads to topics including parsers and programming language interpreters. The concept of monads along with the Haskell do-notation for them has also been generalized to form applicative functors and arrows.

For a long time, Haskell and its derivatives have been the only major users of monads in programming. There also exist formulations in SchemePerlPythonRacketClojure and Scala, and monads have been an option in the design of a new ML standard. Recently F# has included a feature called computation expressions orworkflows, which are an attempt to introduce monadic constructs within a syntax more palatable to programmers with an imperative background.[9]

Motivating examples[edit]

The Haskell programming language is a functional language that makes heavy use of monads, and includessyntactic sugar to make monadic composition more convenient. All of the code samples in this article are written in Haskell unless noted otherwise.

We demonstrate two common examples given when introducing monads: the Maybe monad and the I/O monad. Monads are of course not restricted to the Haskell language, though: the second set of examples shows theWriter monad in JavaScript.

The Maybe monad[edit]

Consider the option type Maybe a, representing a value that is either a single value of type a, or no value at all. To distinguish these, we have two algebraic data type constructors: Just t, containing the value t, orNothing, containing no value.

data Maybe t = Just t | Nothing

We would like to be able to use this type as a simple sort of checked exception: at any point in a computation, the computation may fail, which causes the rest of the computation to be skipped and the final result to beNothing. If all steps of the calculation succeed, the final result is Just x for some value x.

In the following example, add is a function that takes two arguments of type Maybe Int, and returns a result of the same type. If both mx and my have Just values, we want to return Just their sum; but if either mx ormy is Nothing, we want to return Nothing. If we naïvely attempt to write functions with this kind of behavior, we'll end up with a nested series of "if Nothing then Nothing else do something with the x in Just x" cases that will quickly become unwieldy:[1]

add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my =
  case mx of
    Nothing -> Nothing
    Just x  -> case my of
                 Nothing -> Nothing
                 Just y  -> Just (x + y)

To alleviate this, we can define operations for chaining these computations together. The bind binary operator (>>=) chains the results of one computation that could fail, into a function that chooses another computation that could fail. If the first argument is Nothing, the second argument (the function) is ignored and the entire operation simply fails. If the first argument is Just x, we pass x to the function to get a new Maybe value, which may or may not result in a Just value.

(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing  >>= _  =  Nothing    -- A failed computation returns Nothing
(Just x) >>= f  =  f x        -- Applies function f to value x

We already have a value constructor that returns a value without affecting the computation's additional state:Just.

return :: a -> Maybe a
return x = Just x       -- Wraps value x, returning a value of type (Maybe a)

We can then write the example as:

add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my =             -- Adds two values of type (Maybe Int), where each input value can be Nothing
  mx >>= (\x ->         -- Extracts value x if mx is not Nothing
    my >>= (\y ->       -- Extracts value y if my is not Nothing
      return (x + y)))  -- Wraps value (x+y), returning the sum as a value of type (Maybe Int)

Using some additional syntactic sugar known as do-notation, the example can be written as:

add :: Maybe Int -> Maybe Int -> Maybe Int
add mx my = do
  x <- mx
  y <- my
  return (x + y)

Since this type of operation is quite common, there is a standard function in Haskell (liftM2) to take two monadic values (here: two Maybes) and combine their contents (two numbers) using another function (addition), making it possible to write the previous example as

add :: Maybe Int -> Maybe Int -> Maybe Int
add = liftM2 (+)

(Writing out the definition of liftM2 yields the code presented above in do-notation.)

The Writer monad[edit]

The Writer monad allows a process to carry additional information "on the side", along with the computed value. This can be useful to log error or debugging information which is not the primary result.[10]

The following example implements a Writer monad in Javascript:

First, a Writer monad is declared. Function unit creates a new value type from a basic type, with an empty log string attached to it; and bind applies a function to an old value, and returns the new result value with an expanded log. The array brackets work here as the monad's type constructor, creating a value of the monadic type for the Writer monad from simpler components (the value in position 0 of the array, and the log string in position 1).

var unit = function(value) { return [value, ''] };
var bind = function(monadicValue, transformWithLog) {
    var value  = monadicValue[0],
        log = monadicValue[1],
        result = transformWithLog(value);
    return [ result[0], log + result[1] ];
};

pipeline is an auxiliary function that concatenates a sequence of binds applied to an array of functions.

var pipeline = function(monadicValue, functions) {
    for (var key in functions) {
        monadicValue = bind(monadicValue, functions[key]);
    }
    return monadicValue;
};

Examples of functions that return values of the type expected by the above Writer monad:

var squared = function(x) {
    return [x * x, 'was squared.'];
};
 
var halved = function(x) {
    return [x / 2, 'was halved.'];
};

Finally, an example of using the monad to build a pipeline of mathematical functions with debug information on the side:[clarification needed]

pipeline(unit(4), [squared, halved]); // [8, "was squared.was halved."]

The I/O monad[edit]

In a purely functional language, such as Haskell, functions cannot have any externally visible side effects as part of the function semantics. Although a function cannot directly cause a side effect, it can construct a valuedescribing a desired side effect, that the caller should apply at a convenient time.[11] In the Haskell notation, a value of type IO a represents an action that, when performed, produces a value of type a.

We can think of a value of type IO as an action that takes as its argument the current state of the world, and will return a new world where the state has been changed according to the function's return value. For example, the functions doesFileExist and removeFile in the standard Haskell library have the following types

doesFileExist :: FilePath -> IO Bool
removeFile :: FilePath -> IO ()

So, one can think of removeFile as a function that, given a FilePath, returns an IO action; this action will ensure that the world, in this case the underlying file system, won't have a file named by that FilePath when it gets executed. Here, the IO internal value is of type () which means that the caller does not care about any other outcomes. On the other hand, in doesFileExist, the function returns an IO action which wraps a boolean value, True or False; this conceptually represents a new state of the world where the caller knows for certain whether that FilePath is present in the file system or not at the time of the action is performed. The state of the world managed in this way can be passed from action to action, thus defining a series of actions which will be applied in order as steps of state changes. This process is similar to how a temporal logicrepresents the passage of time using only declarative propositions. The following example clarifies in detail how this chaining of actions occurs in a program, again using Haskell.

We would like to be able to describe all of the basic types of I/O operations, e.g. write text to standard output, read text from standard input, read and write files, send data over networks, etc. In addition, we need to be able to compose these primitives to form larger programs. For example, we would like to be able to write:

main :: IO ()
main = do
  putStrLn "What is your name?"
  name <- getLine
  putStrLn ("Nice to meet you, " ++ name ++ "!")

How can we formalize this intuitive notation? To do this, we need to be able to perform some basic operations with I/O actions:

  • We should be able to sequence two I/O operations together. In Haskell, this is written as an infix operator>>, so that putStrLn "abc" >> putStrLn "def" is an I/O action that prints two lines of text to the console. The type of >> is IO a → IO b → IO b, meaning that the operator takes two I/O operations and returns a third that sequences the two together and returns the value of the second.
  • We should have an I/O action which does nothing. That is, it returns a value but has no side effects. In Haskell, this action constructor is called return; it has type a → IO a.
  • More subtly, we should be able to determine our next action based on the results of previous actions. To do this, Haskell has an operator >>= (pronounced bind) with type IO a → (a → IO b) → IO b. That is, the operand on the left is an I/O action that returns a value of type a; the operand on the right is a function that can pick an I/O action based on the value produced by the action on the left. The resulting combined action, when performed, performs the first action, then evaluates the function with the first action's return value, then performs the second action, and finally returns the second action's value.
An example of the use of this operator in Haskell would be getLine >>= putStrLn, which reads a single line of text from standard input and echos it to standard output. Note that the first operator, >>, is just a special case of this operator in which the return value of the first action is ignored and the selected second action is always the same.

It is not necessarily obvious that the three preceding operations, along with a suitable primitive set of I/O operations, allow us to define any program action whatsoever, including data transformations (using lambda expressions), if/then control flow, and looping control flows (using recursion). We can write the above example as one long expression:

main =
  putStrLn "What is your name?" >> 
  getLine >>= \name ->
  putStrLn ("Nice to meet you, " ++ name ++ "!")

The pipeline structure of the bind operator ensures that the getLine and putStrLn operations get evaluated only once and in the given order, so that the side-effects of extracting text from the input stream and writing to the output stream are correctly handled in the functional pipeline. This remains true even if the language performsout-of-order or lazy evaluation of functions.

Clearly, there is some common structure between the I/O definitions and the Maybe definitions, even though they are different in many ways. Monads are an abstraction upon the structures described above, and many similar structures, that finds and exploits the commonalities. The general monad concept includes any situation where the programmer wants to carry out a purely functional computation while a related computation is carried out on the side.

Formal definition[edit]

A monad is a construction that, given an underlying type system, embeds a corresponding type system (called the monadic type system) into it (that is, each monadic type acts as the underlying type). This monadic type system preserves all significant aspects of the underlying type system, while adding features particular to the monad.[note 1]

The usual formulation of a monad for programming is known as a Kleisli triple, and has the following components:

  1. type constructor that defines, for every underlying type, how to obtain a corresponding monadic type. In Haskell's notation, the name of the monad represents the type constructor. If M is the name of the monad and t is a data type, then M t is the corresponding type in the monad.
  2. unit function that maps a value in an underlying type to a value in the corresponding monadic type. The unit function has the polymorphic type t→M t. The result is normally the "simplest" value in the corresponding type that completely preserves the original value (simplicity being understood appropriately to the monad). In Haskell, this function is called return due to the way it is used in the do-notation described later.
  3. binding operation of polymorphic type (M t)→(t→M u)→(M u), which Haskell represents by the infixoperator >>=. Its first argument is a value in a monadic type, its second argument is a function that maps from the underlying type of the first argument to another monadic type, and its result is in that other monadic type. Typically, the binding operation can be understood as having four stages:
    1. The monad-related structure on the first argument is "pierced" to expose any number of values in the underlying type t.
    2. The given function is applied to all of those values to obtain values of type (M u).
    3. The monad-related structure on those values is also pierced, exposing values of type u.
    4. Finally, the monad-related structure is reassembled over all of the results, giving a single value of type (M u).

Given a type constructor M, in most contexts, a value of type M a can be thought of as an action that returns a value of type a. The return operation takes a value from a plain type a and puts it into a monadic container of type M a; the bind operation chains a monadic value of type M a with a function of type a → M b to create a monadic value of type M b.

Monad laws[edit]

For a monad to behave correctly, the definitions must obey a few axioms, together called the monad laws.[12]The ≡ symbol indicates equivalence between two Haskell expressions in the following text.

  • return acts approximately as a neutral element of >>=, in that:
    • (return x) >>= f   ≡   f x
    • >>= return   ≡   m
  • Binding two functions in succession is the same as binding one function that can be determined from them:
    • (>>= f) >>= g   ≡   m >>= ( \x -> (f x >>= g) )

The axioms can also be expressed using expressions in do-block style:

  • do { f x }   ≡   do { v <- return x; f v }
  • do { m }   ≡   do { v <- m; return v }
  • do { x <- m; y <- f x; g y }   ≡   do { y <- do { x <- m; f x }; g y }

or using the monadic composition operator, (>=> g) x = (f x) >>= g:

  • return >=> g   ≡   g
  • >=> return   ≡   f
  • (>=> g) >=> h   ≡   f >=> (>=> h)

fmap and join[edit]

Although Haskell defines monads in terms of the return and bind functions, it is also possible to define a monad in terms of return and two other operations, join and fmap. This formulation fits more closely with the definition of monads in category theory. The fmap operation, with type (tu) → M t→M u,[13] takes a function between two types and produces a function that does the "same thing" to values in the monad. The join operation, with type M (M t)→M t, "flattens" two layers of monadic information into one.

The two formulations are related as follows:

fmap f m = m >>= (return . f)
join n = n >>= id
 
m >>= g   ≡   join (fmap g m)

Here, m has the type M t, n has the type M (M r), f has the type t → u, and g has the type t → M v, where tr,u and v are underlying types.

The fmap function is defined for any functor in the category of types and functions, not just for monads. It is expected to satisfy the functor laws:

fmap idid
fmap (f . g)(fmap f) . (fmap g)

The return function characterizes pointed functors in the same category, by accounting for the ability to "lift" values into the functor. It should satisfy the following law:

return . f ≡ fmap f . return

In addition, the join function characterizes monads:

join . fmap join     ≡ join . join
join . fmap return   ≡ join . return = id
join . fmap (fmap f)fmap f . join

Additive monads [edit]

An additive monad is a monad endowed with a monadic zero mzero and a binary operator mplus satisfying themonoid laws, with the monadic zero as unit. The operator mplus has type M t → M t → M t (where M is the monad constructor and t is the underlying data type), satisfies the associative law and has the zero as both left and right identity. (Thus, an additive monad is also a monoid.)

Binding mzero with any function produces the zero for the result type, just as 0 multiplied by any number is 0.

mzero >>= f   ≡   mzero

Similarly, binding any m with a function that always returns a zero results in a zero

m >>= (\x -> mzero)   ≡   mzero

Intuitively, the zero represents a value in the monad that has only monad-related structure and no values from the underlying type. In the Maybe monad, "Nothing" is a zero. In the List monad, "[]" (the empty list) is a zero.

Syntactic sugar: do-notation [edit]

Although there are times when it makes sense to use the bind operator >>= directly in a program, it is more typical to use a format called do-notation (perform-notation in OCamlcomputation expressions in F#), that mimics the appearance of imperative languages. The compiler translates do-notation to expressions involving>>=. For example, the following code:

a = do x <- [3..4]
       [1..2]
       return (x, 42)

is transformed during compilation into:

a = [3..4] >>= (\x -> [1..2] >>= (\_ -> return (x, 42)))

It is helpful to see the implementation of the list monad, and to know that concatMap maps a function over a list and concatenates (flattens) the resulting lists:

instance Monad [] where
  m >>= f  = concat (map f m)
  return x = [x]
  fail s   = []

Therefore, the following transformations hold and all the following expressions are equivalent:

a = [3..4] >>= (\x -> [1..2] >>= (\_ -> return (x, 42)))
a = [3..4] >>= (\x -> concatMap (\_ -> return (x, 42)) [1..2] )
a = [3..4] >>= (\x -> [(x,42),(x,42)] )
a = concatMap (\x -> [(x,42),(x,42)] ) [3..4]
a = [(3,42),(3,42),(4,42),(4,42)]

Notice that the list [1..2] is not used. The lack of a left-pointing arrow, translated into a binding to a function that ignores its argument, indicates that only the monadic structure is of interest, not the values inside it, e.g. for a state monad this might be used for changing the state without producing any more result values. The do-block notation can be used with any monad as it is simply syntactic sugar for >>=.

The following definitions for safe division for values in the Maybe monad are also equivalent:

x // y = do
  a <- x  -- Extract the values "inside" x and y, if there are any.
  b <- y
  if b == 0 then Nothing else Just (a / b)
 
x // y = x >>= (\a -> y >>= (\b -> if b == 0 then Nothing else Just (a / b)))

A similar example in F# using a computation expression:

let readNum () =
  let s = Console.ReadLine()
  let succ,v = Int32.TryParse(s)
  if (succ) then Some(v) else None
 
let secure_div = 
  maybe { 
    let! x = readNum()
    let! y = readNum()
    if (y = 0) 
    then None
    else return (x / y)
  }

The syntactic sugar of the maybe block would get translated internally to the following expression:

maybe.Delay(fun () ->
  maybe.Bind(readNum(), fun x ->
    maybe.Bind(readNum(), fun y ->
      if (y=0) then None else maybe.Return( x/y ))))

Generic monadic functions[edit]

Given values produced by safe division, we might want to carry on doing calculations without having to check manually if they are Nothing (i.e. resulted from an attempted division by zero). We can do this using a "lifting" function, which we can define not only for Maybe but for arbitrary monads. In Haskell this is called liftM2:

liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
liftM2 op mx my = do
    x <- mx
    y <- my
    return (op x y)

Recall that arrows in a type associate to the right, so liftM2 is a function that takes a binary function as an argument and returns another binary function. The type signature says: If m is a monad, we can "lift" any binary function into it. For example:

(.*.) :: (Monad m, Num a) => m a -> m a -> m a
x .*. y = liftM2 (*) x y

defines an operator (.*.) which multiplies two numbers, unless one of them is Nothing (in which case it again returns Nothing). The advantage here is that we need not dive into the details of the implementation of the monad; if we need to do the same kind of thing with another function, or in another monad, using liftM2 makes it immediately clear what is meant (see Code reuse).

Mathematically, the liftM2 operator is defined by:

\text{liftM2} \colon \forall M \colon \text{monad}, \; (A_1 \to A_2 \to R) \to M \, A_1 \to M \, A_2 \to M \, R =  op \mapsto m_1 \mapsto m_2 \mapsto \text{bind} \; m_1 \; (a_1 \mapsto \text{bind} \; m_2 \; (a_2 \mapsto \text{return} \; (op \, a_1 \, a_2)))

Other examples[edit]

Identity monad[edit]

The simplest monad is the identity monad, which attaches no information to values.

Id t = t
return x = x
x >>= f = f x

A do-block in this monad performs variable substitution; do {x <- 2; return 3*x} results in 6.

From the category theory point of view, the identity monad is derived from the adjunction between identity functors.

Collections[edit]

Some familiar collection types, including listssets, and multisets, are monads. The definition for lists is given here.

-- "return" constructs a one-item list.
return x = [x]
-- "bind" concatenates the lists obtained by applying f to each item in list xs.
xs >>= f = concat (map f xs)
-- The zero object is an empty list.
mzero = []

List comprehensions are a special application of the list monad. For example, the list comprehension [ 2*x | x <- [1..n], isOkay x] corresponds to the computation in the list monad do {x <- [1..n]; if isOkay x then return (2*x) else mzero;}.

The notation of list comprehensions is similar to the set-builder notation, but sets can't be made into a monad, since there's a restriction on the type of computation to be comparable for equality, whereas a monad does not put any constraints on the types of computations. Actually, the Set is a restricted monad.[14] The monads for collections naturally represent nondeterministic computation. The list (or other collection) represents all the possible results from different nondeterministic paths of computation at that given time. For example, when one executes x <- [1,2,3,4,5], one is saying that the variable x can non-deterministically take on any of the values of that list. If one were to return x, it would evaluate to a list of the results from each path of computation. Notice that the bind operator above follows this theme by performing f on each of the current possible results, and then it concatenates the result lists together.

Statements like if condition x y then return () else mzero are also often seen; if the condition is true, the non-deterministic choice is being performed from one dummy path of computation, which returns a value we are not assigning to anything; however, if the condition is false, then the mzero = [] monad value non-deterministically chooses from 0 values, effectively terminating that path of computation. Other paths of computations might still succeed. This effectively serves as a "guard" to enforce that only paths of computation that satisfy certain conditions can continue. So collection monads are very useful for solving logic puzzles, Sudoku, and similar problems.

In a language with lazy evaluation, like Haskell, a list is evaluated only to the degree that its elements are requested: for example, if one asks for the first element of a list, only the first element will be computed. With respect to usage of the list monad for non-deterministic computation that means that we can non-deterministically generate a lazy list of all results of the computation and ask for the first of them, and only as much work will be performed as is needed to get that first result. The process roughly corresponds to backtracking: a path of computation is chosen, and then if it fails at some point (if it evaluates mzero), then itbacktracks to the last branching point, and follows the next path, and so on. If the second element is then requested, it again does just enough work to get the second solution, and so on. So the list monad is a simple way to implement a backtracking algorithm in a lazy language.

From the category theory point of view, collection monads are derived from adjunctions between a free functorand an underlying functor between the category of sets and a category of monoids. Taking different types of monoids, we obtain different types of collections, as in the table below:

Type of collectionsType of monoids
listmonoid
finite multisetcommutative monoid
finite setidempotent commutative monoid
finite permutationidempotent non-commutative monoid

State monads[edit]

A state monad allows a programmer to attach state information of any type to a calculation. Given any value type, the corresponding type in the state monad is a function which accepts a state, then outputs a new state (of type s) along with a return value (of type t).

type State s t = s -> (t, s)

Note that this monad, unlike those already seen, takes a type parameter, the type of the state information. The monad operations are defined as follows:

-- "return" produces the given value without changing the state.
return x = \s -> (x, s)
-- "bind" modifies m so that it applies f to its result.
m >>= f = \r -> let (x, s) = m r in (f x) s

Useful state operations include:

get = \s -> (s, s) -- Examine the state at this point in the computation.
put s = \_ -> ((), s) -- Replace the state.
modify f = \s -> ((), f s) -- Update the state

Another operation applies a state monad to a given initial state:

runState :: State s a -> s -> (a, s)
runState t s = t s

do-blocks in a state monad are sequences of operations that can examine and update the state data.

Informally, a state monad of state type S maps the type of return values T into functions of type S \rarr T \times S, where S is the underlying state. The return function is simply:

\text{return} \colon T \rarr S \rarr T \times S = t \mapsto s \mapsto (t, s)

The bind function is:

\text{bind} \colon (S \rarr T \times S) \rarr (T \rarr S \rarr T' \times S) \rarr S \rarr T' \times S \ = m \mapsto k \mapsto s \mapsto (k \ t \ s') \quad \text{where} \; (t, s') = m \, s.

From the category theory point of view, a state monad is derived from the adjunction between the product functor and the exponential functor, which exists in any cartesian closed category by definition.

Environment monad[edit]

The environment monad (also called the reader monad and the function monad) allows a computation to depend on values from a shared environment. The monad type constructor maps a type T to functions of type E→ T, where E is the type of the shared environment. The monad functions are:

\text{return} \colon T \rarr E \rarr T = t \mapsto e \mapsto t
\text{bind} \colon (E \rarr T) \rarr (T \rarr E \rarr T') \rarr E \rarr T' = r \mapsto f \mapsto e \mapsto f \, (r \, e) \, e

The following monadic operations are useful:

\text{ask} \colon E \rarr E = \text{id}_E
\text{local} \colon (E \rarr E) \rarr (E \rarr T) \rarr E \rarr T = f \mapsto c \mapsto e \mapsto c \, (f \, e)

The ask operation is used to retrieve the current context, while local executes a computation in a modified subcontext. As in the state monad, computations in the environment monad may be invoked by simply providing an environment value and applying it to an instance of the monad.

Writer monad[edit]

The writer monad allows a program to compute various kinds of auxiliary output which can be "composed" or "accumulated" step-by-step, in addition to the main result of a computation. It is often used for logging or profiling. Given the underlying type T, a value in the writer monad has type W × T, where W is a type endowed with an operation satisfying the monoid laws. The monad functions are simply:

\text{return} \colon T \rarr W \times T = t \mapsto (\epsilon, t)
\text{bind} \colon (W \times T) \rarr (T \rarr W \times T') \rarr W \times T' = (w, t) \mapsto f \mapsto (w * w',\, t') \quad \text{where} \; (w', t') = f \, t

where ε and * are the identity element of the monoid W and its associative operation, respectively.

The tell monadic operation is defined by:

\text{tell} \colon W \rarr (W \times 1) = w \mapsto (w, ())

where 1 and () denote the unit type and its trivial element. It is used in combination with bind to update the auxiliary value without affecting the main computation.

Continuation monad[edit]

continuation monad with return type R maps type T into functions of type \left( T \rarr R \right) \rarr R. It is used to model continuation-passing style. The return and bind functions are as follows:

\text{return} \colon T \rarr \left( T \rarr R \right) \rarr R = t \mapsto f \mapsto f \, t
\text{bind} \colon \left( \left( T \rarr R \right) \rarr R \right) \rarr \left( T \rarr \left( T' \rarr R \right) \rarr R \right) \rarr \left( T' \rarr R \right) \rarr R= c \mapsto f \mapsto k \mapsto c \, \left( t \mapsto f \, t \, k \right)

The call-with-current-continuation function is defined as follows:

\text{call/cc} \colon \left( \left( T \rarr \left( T' \rarr R \right) \rarr R \right) \rarr \left( T \rarr R \right) \rarr R \right) \rarr \left( T \rarr R \right) \rarr R = f \mapsto k \mapsto \left( f \left( t \mapsto x \mapsto k \, t \right) \, k \right)

Others[edit]

Other concepts that researchers have expressed as monads include:

Free monads[edit]

Comonads[edit]

Comonads are the categorical dual of monads. They are defined by a type constructor W T and two operations:extract with type W T → T for any T, and extend with type (W T → T' ) → W T → W T' . The operations extendand extract are expected to satisfy these laws:

\text{extend} \,\, \text{extract} = \text{id}
\text{extract} \circ (\text{extend} \, f) = f
(\text{extend} \, f) \circ (\text{extend} \, g) = \text{extend} \, (f \circ (\text{extend} \, g))

Alternatively, comonads may be defined in terms of operations fmapextract and duplicate. The fmap andextract operations define W as a copointed functor. The duplicate operation characterizes comonads: it has type W T → W (W T) and satisfies the following laws:

\text{extract} \circ \text{duplicate} = \text{id}
\text{fmap} \, \text{extract} \circ \text{duplicate} = \text{id}
\text{duplicate} \circ \text{duplicate} = \text{fmap} \, \text{duplicate} \circ \text{duplicate}

The two formulations are related as follows:

\text{fmap}: (A \rarr B) \rarr \mathrm{W} \, A \rarr \mathrm{W} \, B = f \mapsto \text{extend} \, (f \circ \text{extract})
\text{duplicate}: \mathrm{W} \, A \rarr \mathrm{W} \, \mathrm{W} \, A = \text{extend} \, \text{id}
\text{extend}: (\mathrm{W} \, A \rarr B) \rarr \mathrm{W} \, A \rarr \mathrm{W} \, B = f \mapsto (\text{fmap} \, f) \circ \text{duplicate}

Whereas monads could be said to represent side-effects, a comonad W represents a kind of context. Theextract functions extracts a value from its context, while the extend function may be used to compose a pipeline of "context-dependent functions" of type W A → B.

Identity comonad[edit]

The identity comonad is the simplest comonad: it maps type T to itself. The extract operator is the identity and the extend operator is function application.

Product comonad[edit]

The product comonad maps type T into tuples of type C \times T, where C is the context type of the comonad. The comonad operations are:

\text{extract}: (C \times T) \rarr T = (c, t) \mapsto t
\text{extend}: ((C \times A) \rarr B) \rarr C \times A \rarr C \times B = f \mapsto (c, a) \mapsto (c, f \, (c, a))
\text{fmap}: (A \rarr B) \rarr (C \times A) \rarr (C \times B) = (c, a) \mapsto (c, f \, a)
\text{duplicate}: (C \times A) \rarr (C \times (C \times A)) = (c, a) \mapsto (c, (c, a))

Function comonad[edit]

The function comonad maps type T into functions of type M \rarr T, where M is a type endowed with amonoid structure. The comonad operations are:

\text{extract}: (M \rarr T) \rarr T = f \mapsto f \, \varepsilon
\text{extend}: ((M \rarr A) \rarr B) \rarr (M \rarr A) \rarr M \rarr B = f \mapsto g \mapsto m \mapsto f \, (m' \mapsto g \, (m * m'))
\text{fmap}: (A \rarr B) \rarr (M \rarr A) \rarr M \rarr B = f \mapsto g \mapsto (f \circ g)
\text{duplicate}: (M \rarr A) \rarr M \rarr (M \rarr A) = f \mapsto m \mapsto m' \mapsto f \, (m * m')

where ε is the identity element of M and * is its associative operation.

Costate comonad[edit]

The costate comonad maps a type T into type (S \rarr T) \times S, where S is the base type of the store. The comonad operations are:

\text{extract}: ((S \rarr T) \times S) \rarr T = (f, s) \mapsto f \, s
\text{extend}: (((S \rarr A) \times S) \rarr B) \rarr ((S \rarr A) \times S) \rarr (S \rarr B) \times S \,= f \mapsto (g, s) \mapsto ((s' \mapsto f \, (g, s')), s)
\text{fmap}: (A \rarr B) \rarr ((S \rarr A) \times S) \rarr (S \rarr B) \times S = f \mapsto (f', s) \mapsto (f \circ f', s)
\text{duplicate}: ((S \rarr A) \times S) \rarr (S \rarr ((S \rarr A) \times S)) \times S = (f, s) \mapsto ((s' \mapsto (f, s')), s)

See also[edit]

Notes[edit]

  1. Jump up^ Technically, the monad is not required to preserve the underlying type. For example, the trivial monad in which there is only one polymorphic value which is produced by all operations satisfies all of the axioms for a monad. Conversely, the monad is not required to add any additional structure; the identity monad, which simply preserves the original type unchanged, also satisfies the monad axioms and is useful as a recursive base for monad transformers.

References[edit]

  1. Jump up to:a b c O'Sullivan, Bryan; Goerzen, John; Stewart, Don. Real World Haskell. O'Reilly, 2009. ch. 14.
  2. Jump up^ "A physical analogy for monads". Archived from the original on 10 Sep 2010.
  3. Jump up^ Eric Lippert. "Monads, part one". Retrieved 6 September 2013.
  4. Jump up^ Wadler, PhilipComprehending Monads. Proceedings of the 1990 ACM Conference on LISP and Functional Programming, Nice. 1990.
  5. Jump up^ Wadler, Philip. The Essence of Functional Programming. Conference Record of the Nineteenth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages. 1992.
  6. Jump up^ Hughes, J. (2005). Programming with arrows. In Advanced Functional Programming (pp. 73-129). Springer Berlin Heidelberg. "
  7. Jump up^ De Meuter, Wolfgang. "Monads as a theoretical foundation for AOP". Workshop on Aspect Oriented Programming, ECOOP 1997.
  8. Jump up to:a b Moggi, Eugenio (1991). "Notions of computation and monads"Information and Computation 93 (1).
  9. Jump up^ "Some Details on F# Computation Expressions". Retrieved 2007-12-14.
  10. Jump up^ "The Writer monad". haskell.cz.
  11. Jump up^ Peyton Jones, Simon L.; Wadler, Philip. Imperative Functional Programming. Conference record of the Twentieth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, Charleston, South Carolina. 1993
  12. Jump up^ "Monad laws"HaskellWiki. haskell.org. Retrieved 2011-12-11.
  13. Jump up^ "Functors, Applicative Functors and Monoids". learnyouahaskell.com.
  14. Jump up^ How to make Data.Set a monad shows an implementation of the Set restricted monad in Haskell

External links[edit]

Haskell monad tutorials[edit]

Older tutorials[edit]

Other documentation[edit]

Scala monad tutorials[edit]

Monads in other languages[edit]


반응형
Posted by blueasa
, |
public static class Extensions
{
    public static bool TryGetKey<K, V>(this IDictionary<K, V> instance, V value, out K key)
    {
        foreach (var entry in instance)
        {
            if (!entry.Value.Equals(value))
            {
                continue;
            }
            key = entry.Key;
            return true;
        }
        key = default(K);
        return false;
    }
}

the usage is also so simple

int key = 0;
if (myDictionary.TryGetKey("twitter", out key))
{
    // successfully got the key :)
}



Link : http://stackoverflow.com/questions/4001908/get-dictionary-key-by-using-the-dictionary-value



[참조] https://www.dotnetperls.com/extension

반응형

'Programming > C#' 카테고리의 다른 글

C# 강의  (0) 2014.08.29
람다 식  (0) 2014.08.29
[C#] How to get/set using index for a Dictionary?  (0) 2014.08.06
NTP 서버에서 시간 가져오기(SNTP)  (0) 2014.07.14
C# 외부 프로그램 종료하기  (0) 2014.05.20
Posted by blueasa
, |