سؤال

وعندما يكون لدي بعض من وظيفة من نوع مثل

f :: (Ord a) => a -> a -> Bool
f a b = a > b

وأود جعل وظيفة التي التفاف هذه الوظيفة مع لا.

ومنها مثلا. جعل وظيفة مثل هذا

g :: (Ord a) => a -> a -> Bool
g a b = not $ f a b

وأنا يمكن أن تجعل combinator مثل

n f = (\a -> \b -> not $ f a b)

ولكن لا أعرف كيف.

*Main> let n f = (\a -> \b -> not $ f a b)
n :: (t -> t1 -> Bool) -> t -> t1 -> Bool
Main> :t n f
n f :: (Ord t) => t -> t -> Bool
*Main> let g = n f
g :: () -> () -> Bool

وماذا أفعل الخطأ؟

والسؤال مكافأة كيف أستطيع أن أفعل ذلك من أجل وظيفة مع أكثر وخشية المعلمات منها مثلا.

t -> Bool
t -> t1 -> Bool
t -> t1 -> t2 -> Bool
t -> t1 -> t2 -> t3 -> Bool
هل كانت مفيدة؟

المحلول

وإلا إذا كنت تريد أن تذهب القرصنة حولها مع typeclasses، الذي هو أفضل اليسار للتجارب الفكر وإثبات المفهوم، أنت فقط لا نعمم على حجج متعددة. لا تحاول.

وأما عن السؤال الرئيسي، يتم حل هذه أكثر بأناقة مع الدلالي combinators محرر كونال إليوت . A الدلالي محرر combinator هي وظيفة مع نوع مثل:

(a -> b) -> F(a) -> F(b)

وأين F(x) هو بعض التعبير تنطوي x. وهناك أيضا "contravariant" محرر combinators التي تأخذ (b -> a) بدلا من ذلك. حدسي، وcombinator محرر يختار جانب بعض قيمة أكبر للعمل على. واحد تحتاج يسمى result:

result = (.)

وانظر إلى نوع من التعبير الذي تحاول تعمل على:

a -> a -> Bool

وكانت النتيجة (مجال مقابل) من هذا النوع هو a -> Bool، ونتيجة ل<م> أن النوع هو Bool، وهذا ما كنت تحاول تطبيق not ل. لذلك لتطبيق not إلى نتيجة نتيجة f وظيفة، تكتب:

(result.result) not f

وهذا يعمم بشكل جميل. وفيما يلي بعض أكثر combinators:

argument = flip (.)     -- contravariant

first f (a,b) = (f a, b)
second f (a,b) = (a, f b)

left f (Left x) = Left (f x)
left f (Right x) = Right x
...

وحتى إذا كان لديك x قيمة من نوع:

Int -> Either (String -> (Int, Bool)) [Int]

وتريد تطبيق not إلى منطقية، كنت مجرد توضيح مسار للوصول إلى هناك:

(result.left.result.second) not x

وأوه، وإذا كنت قد حصلت على المنفذون بعد، ستلاحظ أن fmap هو combinator المحرر. في الواقع، ما سبق يمكن توضيح:

(fmap.left.fmap.fmap) not x

ولكن اعتقد انها أكثر وضوحا لاستخدام أسماء الموسعة.

واستمتع.

نصائح أخرى

والواقع، والقيام arity تعسفي في الطبقات نوع تبين أن يكون من السهل للغاية:

module Pred where

class Predicate a where
  complement :: a -> a

instance Predicate Bool where
  complement = not

instance (Predicate b) => Predicate (a -> b) where
  complement f = \a -> complement (f a)  
  -- if you want to be mysterious, then
  -- complement = (complement .)
  -- also works

ge :: Ord a => a -> a -> Bool
ge = complement (<)

وشكرا لافتا إلى هذه المشكلة باردة. أنا أحب هاسكل.

ون combinator الخاص بك يمكن أن تكون مكتوبة:

n = ((not .) .)

وأما بالنسبة لمسألة المكافأة الخاصة بك، والطريقة التقليدية في جميع أنحاء سيكون لإنشاء العديد من هذه:

lift2 = (.).(.)
lift3 = (.).(.).(.)
lift4 = (.).(.).(.).(.)
lift5 = (.).(.).(.).(.).(.)

وغيرها.

ورد: <م> ماذا أفعل الخطأ :

وأعتقد combinator الخاص بك على ما يرام، ولكن عندما كنت اود-ربط ذلك على أعلى مستوى، واحد من "القواعد الافتراضية" مزعج هاسكل تأتي في اللعب والربط ليست معممة:

Prelude> :ty (n f)
(n f) :: (Ord t) => t -> t -> Bool
Prelude> let g = n f
Prelude> :ty g
g :: () -> () -> Bool

وأعتقد أنك قد يكون الحصول على مضروب من قبل 'تقييد أحاد الشكل "كما ينطبق على كتابة فصول. في أي حال، إذا كنت الخروج من حلقة ذات المستوى الأعلى ووضع الأمور في ملف منفصل مع نوع توقيع صريح، كل شيء يعمل بشكل جيد:

module X where

n f = (\a -> \b -> not $ f a b)
f a b = a > b

g :: Ord a => a -> a -> Bool
g = n f

<القوي> مسألة مكافأة : لللقيام بذلك مع المزيد والمزيد من المعلمات نوع، يمكنك محاولة اللعب الحيل الاسقربوط مع نظام من الدرجة النوع. ورقتين للتشاور وهيوز وCLAESSEN في على QuickCheck ورقة رالف هينز في <ل أ href = "http://www.informatik.uni-bonn.de/~ralf/publications/Masses.pdf" يختلط = "noreferrer"> الوراثة للجماهير .

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top