2011-08-21 45 views
13

Tôi nghĩ rằng đầu óc của tôi đang bùng nổ cố gắng tìm ra Funcs ... Nếu điều này không có ý nghĩa, tôi xin lỗi, ngay bây giờ nó hợp lý với tôi nhưng đã lâu rồi ...Chuyển đổi Func <T, String> thành Func <T, bool>

1) Giả sử bạn có một func mà mất trong T và kết quả đầu ra một chuỗi:

Func<T, string> 

bạn có thể chuyển đổi đó vào một func thu nhận một T và trả về một bool dựa trên một số logic (trong trường hợp này nếu chuỗi trả về trống (String.IsNullOrWhiteSpace)?

Func<T, bool> 

2) Bạn có thể làm điều tương tự nếu bạn đang đưa ra một

Expression<Func<T, string>> 

và cần phải chuyển nó sang một

Func<T, bool> 

trả về đúng/sai dựa trên nếu chuỗi trả lại là trống (String.IsNullOrWhiteSpace)?

Cảm ơn

Trả lời

11

cho phần đầu tiên bạn thậm chí có thể làm cho một số "cao" chức năng -order:



Func<A,C> MapFun<A,B,C>(Func<A,B> input, Func<B,C> transf) 
{ 
    return a => transf(input(a)); 
} 

sử dụng với



Func <T,string> test = ... 
var result = MapFun(test, String.IsNullOrWhiteSpace); 

(Tôi hy vọng C# loại suy luận kiểu đang làm việc ở đây)

Nếu bạn định nghĩa này như là phần mở rộng trên Func nó được dễ dàng hơn:


public static class FuncExtension 
{ 
    public static Func<A,C> ComposeWith<A,B,C>(this Func<A,B> input, Func<B,C> f) 
    { 
     return a => f(input(a)); 
    } 
} 

đây là một thử nghiệm rất đơn giản:


Func<int, string> test = i => i.ToString(); 
var result = test.ComposeWith(string.IsNullOrEmpty); 

Đối với một thứ hai: Tôi nghĩ rằng bạn có thể biên dịch các biểu thức thành một "thực" Func và sau đó sử dụng mã trên. see MSDN Docs on Expression.Compile

PS: đổi tên các chức năng để đáp ứng tốt hơn đó là ý định (hàm hợp của nó)

+0

Tôi đoán bạn có nghĩa là "suy luận loại" và không phải là "loại nhiễu";) –

+0

Cảm ơn! sau khi bạn nhìn vào câu trả lời nó có ý nghĩa hoàn chỉnh. Nhiều câu trả lời chính xác nhưng câu trả lời của bạn là câu trả lời đầu tiên và đầy đủ để bạn có thể kiểm tra séc. Cảm ơn tất cả mọi người! – Peter

3

Ông có thể không định nghĩa nó như là một đại biểu riêng biệt:

Func<T, string> func1 = t => t.ToString(); 
Func<T, bool> func2 = t => string.IsNullOrEmpty(func1(t)); 
2

Đối với phần đầu tiên kỹ thuật này được gọi là hàm hợp tức là bạn soạn 2 chức năng để tạo ra một chức năng mới. Trong trường hợp của bạn, bạn có một hàm Func<T,String> và một chức năng (như chuỗi rỗng hoặc null) mà là loại Func<string,bool>, sử dụng hàm hợp bạn có thể soạn hai chức năng này để tạo ra một chức năng mới của loại Func<T,Bool>

ngôn ngữ lập trình chức năng Đa có thành phần hàm này đã được định nghĩa trong thư viện chuẩn của chúng hoặc trong chính ngôn ngữ đó. Nhưng không khó để tạo một ngôn ngữ cho ngôn ngữ của bạn nếu ngôn ngữ hỗ trợ các hàm như là các giá trị lớp đầu tiên.

Trong C# bạn có thể sử dụng chức năng dưới đây mà sẽ cho phép bạn soạn chức năng:

public static Func<X,Z> Compose<X,Y,Z>(Func<X,Y> a, Func<Y,Z> b) 
{ 
    return (v) => b(a(v)); 
} 
2

Để 1: Có (Bạn cũng có thể parametrize bool và string):

Func<T, bool> Compose<T>(Func<T, string> source, Func<string, bool>map) 
{ 
    return x => map(source(x)); 
} 

Để 2 : Có, nhưng bạn cần phải biên dịch biểu thức trước tiên:

Func<T, bool> Compose<T>(Expression<Func<T, string>> source, Func<string, bool> map) 
{ 
    return x => compose(source.Compile(), map) 
} 

.Compile sẽ biên dịch biểu thức i vào một phương thức CLR động mà bạn có thể gọi với đại biểu được trả về.

Bạn có thể sử dụng mã này như sau:

Func<int, string> ts = i => i.ToString(); 
var result = Compose(ts, string.IsNullOrEmpty); 

Bằng cách này, trong trường hợp này bạn thực sự nên viết một hàm bậc cao. Những gì bạn đang làm ở đây (đại số) là sáng tác monoids. Ghi nhớ function composition? f . g := f(g(x)) là những gì bạn đang làm ở đây.

Hãy suy nghĩ nguồn là g:A->B và ánh xạ là f:B->C (trong đó A, B và C được đặt) sao cho kết quả của f . gh:A->C. Nhân tiện, toán tử . thường được xây dựng thành các ngôn ngữ lập trình hàm, chẳng hạn như Haskell và đạt được điều tương tự như hàm compose của bạn (nhưng với cú pháp rõ ràng hơn).

Các vấn đề liên quan